class GxG::Database::PersistedArray

Class Place-holder Definitions

Public Class Methods

new(settings = {}) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 651
def initialize(settings = {})
  # 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>}
  #
  if settings.is_a?(::Hash)
    unless ::GxG::valid_uuid?(settings[:credential])
      raise ArgumentError, "You must supply a valid credential UUID (37 character limit) as a String or Symbol"
    end
    @quick = settings[:quick]
    @credential = settings[:credential].to_sym
    @reservation = nil
    @delegate = settings[:delegate]
    if settings[:parent].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
      @parent = settings[:parent]
    else
      @parent = nil
    end
    @constraint = settings[:constraint]
    if settings[:database].is_a?(::GxG::Database::Database)
      if settings[:database].open?()
        the_uuid = settings[:uuid]
        if the_uuid.is_a?(::Symbol)
          the_uuid = the_uuid.to_s
        end
        # TODO: validate uuid pattern
        if settings[:title].is_a?(::String)
          the_title = settings[:title]
        else
          the_title = ("Untitled PersistedArray " << (settings[:database].connector()[:element_array].count.to_s))
        end
        unless ::GxG::valid_uuid?(the_uuid)
          # without specifying a uuid, the implied intent is to create a new PersistedArray
          the_uuid = ::GxG::uuid_generate()
          while ((settings[:database].connector()[:element_array].filter({:uuid => the_uuid}).count > 0) or (settings[:database].connector()[:element_array].filter({:uuid => the_uuid}).count > 0))
            the_uuid = ::GxG::uuid_generate()
          end
          # create blank array record
          new_dbid = settings[:database].connector()[:element_array].insert({:uuid => (the_uuid), :title => (the_title), :constraint => (@constraint.to_s)})
          #
          @db_address = {:database => (settings[:database]), :table => :element_array, :dbid => (new_dbid)}
          if @parent
            @permission = @parent.get_permissions()
            # settings[:database].enforce_permission_policy({:action => :extend, :credential => @credential, :source => settings[:parent], :destination => self})
            #                  settings[:database].extend_element_permissions(settings[:parent].db_address()[:table], settings[:parent].db_address()[:dbid], :element_array, new_dbid)
          else
            # create raw permissions for this element
            @permission = {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true}
            # settings[:database].assign_element_permission(:element_array, new_dbid, @credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
            # settings[:database].enforce_permission_policy({:action => :extend, :credential => @credential, :source => self, :destination => self})
          end
          settings[:database].assign_element_permission(:element_array, new_dbid, @credential, @permission)
        end
        # mount according to uuid
        if the_uuid
          # mount
          record = settings[:database].connector()[:element_array].filter({:uuid => (the_uuid)}).first
          if record
            @uuid = the_uuid.to_sym
            @title = record[:title].to_s
            @version = record[:version].to_f
            @db_address = {:database => (settings[:database]), :table => :element_array, :dbid => (record[:dbid])}
            @element_links = []
            if record[:constraint].to_s.size > 0
              @constraint = record[:constraint].to_sym
            else
              @constraint = nil
            end
            unless @permission
              @permission = @db_address[:database].effective_element_permission(@db_address[:table], @db_address[:dbid], @credential)
            end
            # @read_reservation = @db_address[:database].reserve_element_locks(@credential, (@db_address[:database].element_manifest(@db_address[:table], @db_address[:dbid])), :read)
            #
            load_element_links
            #
          else
            raise Exception, "Unable to mount the PersistedArray record"
          end
        else
          raise Exception, "Unable to mount the PersistedArray record"
        end
        #
      else
        raise Exception, "Database not available for storage"
      end
      #
    else
      raise Exception, "Invalid Database object"
    end
    #
  else
    raise ArgumentError, "You must supply a hash of details"
  end
  #
end

Public Instance Methods

<<(*args) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1303
def <<(*args)
  if args.size > 0
    args.each do |item|
      self[(@element_links.size)] = item
    end
  end
  self
end
[](indexer=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1203
def [](indexer=nil)
  result = nil
  # if exists
  # if is not loaded, load element (if String or ByteArray)
  if self.alive?()
    if @db_address[:database].open?()
      if indexer.is_a?(::Integer)
        if @element_links[(indexer)]
          if @element_links[(indexer)][:content].is_any?(::String, ::GxG::ByteArray)
            unless @element_links[(indexer)][:loaded] == true
              # ### Load Base Element contents from the database.
              if @element_links[(indexer)][:content].is_a?(::String)
                if @element_links[(indexer)][:record][:element_text_uuid].to_s.size > 0
                  @db_address[:database].connector()[:text_page].filter({:parent_uuid => @element_links[(indexer)][:record][:element_text_uuid].to_s}).order(:ordinal).each do |text_page|
                    @element_links[(indexer)][:content] << text_page[:content]
                  end
                else
                  @element_links[(indexer)][:content] = @element_links[(indexer)][:record][:element_text].to_s
                end
              else
                @db_address[:database].connector()[:binary_page].filter({:parent_uuid => @element_links[(indexer)][:record][:element_binary_uuid].to_s}).order(:ordinal).each do |binary_page|
                  @element_links[(indexer)][:content] << binary_page[:content]
                end
              end
              @element_links[(indexer)][:loaded] = true
            end
          end
          result = @element_links[(indexer)][:content]
        end
      else
        raise ArgumentError, "You must specify with an Integer, not a #{indexer.class.inspect}"
      end
    else
      raise Exception, "Database not available"
    end
  else
    raise Exception, "Attempted to access a defunct structure"
  end
  result
end
[]=(indexer=nil, value=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 892
def []=(indexer=nil, value=nil)
  # Only works with Integer indexes.
  unless self.alive?()
    raise Exception, "Attempted to alter a defunct structure"
  end
  unless @db_address[:database].open?()
    raise Exception, "Database not available"
  end
  result = nil
  if indexer.is_a?(::Integer)
    # Review : rewrite ????
    if value.is_any?(::GxG::Database::Database::valid_field_classes()) || value.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray, ::Hash, ::Array)
      unless self.write_reserved?()
        self.get_reservation()
      end
      if self.write_reserved?()
        # Further screen value provided:
        # ### Check provided PersistedHashes and PersistedArrays
        if value.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
          unless value.db_address()
            raise Exception, "The structure you are attaching is Deactivated (not supported)."
          end
          if value.structure_attached?()
            # Review : experimental - auto-detach from prior structural relationship and reassign here.
            # raise Exception, "Cross linked structures not supported"
            value.structure_detach
          end
          value.search do |the_value, the_selector, the_container|
            if the_value.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
              unless the_value.db_address()
                raise Exception, "The structure you are attaching has a Deactivated item within it (not supported)."
              end
            end
          end
        end
        # ### Check provided Hashes and Arrays
        if value.is_any?(::Hash, ::Array)
          value.search do |the_value, the_selector, the_container|
            if the_value.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
              unless the_value.db_address()
                raise Exception, "The structure you are attaching has a Deactivated item within it (not supported)."
              end
              if @db_address[:database].structure_attached?(the_value.uuid.to_s) && the_container.is_any?(::Hash, ::Array)
                raise Exception, "The structure you are attaching has a cross-linked structure within it (cross linked structures not supported)."
              end
            end
            unless the_value.is_any?(::GxG::Database::Database::valid_field_classes()) || the_value.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray, ::Hash, ::Array)
              raise Exception, "The structure you are attaching has an unpersistable item within it (not supported)."
            end
          end
        end
        # ### Property Exists?
        if @element_links[(indexer)]
          # set property to value
          operation = :set_value
        else
          if @format
            raise Exception, "Formatted - the structure cannot be altered"
          else
            # add property : value pair
            operation = :add_value
          end
        end
        # ### Prepare new value
        new_value = {
          :linkid => nil,
          :content => nil,
          :loaded => false,
          :state => 0,
          :record => {
            :parent_uuid => @uuid.to_s,
            :ordinal => 0,
            :version => 0.0,
            :element => "element_boolean",
            :element_boolean => -1,
            :element_integer => 0,
            :element_float => 0.0,
            :element_bigdecimal => ::BigDecimal.new("0.0"),
            :element_datetime => ::DateTime.now,
            :time_offset => 0.0,
            :time_prior => 0.0,
            :time_after => 0.0,
            :length => 0,
            :element_text => "",
            :element_text_uuid => "",
            :element_binary_uuid => "",
            :element_array_uuid => "",
            :element_hash_uuid => ""
          }
        }
        #
        if value.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
          # ### Assimilate PersistedHash or PersistedArray
          new_value[:content] = value
          new_value[:loaded] = true
          new_value[:state] = new_value[:content].hash
          # Note: version is sync'd here, but don't rely upon property version with linked structures, but use structure's version method.
          new_value[:record][:version] = new_value[:content].version()
          if value.is_a?(::GxG::Database::PersistedHash)
            new_value[:record][:element] = "element_hash"
            new_value[:record][:element_hash_uuid] = value.uuid.to_s
          else
            new_value[:record][:element] = "element_array"
            new_value[:record][:element_array_uuid] = value.uuid.to_s
          end
        else
          # ### Persist Hashes and Arrays
          if value.is_any?(::Hash, ::Array)
            new_value[:content] = @db_address[:database].iterative_persist(value,@credential)
            new_value[:loaded] = true
            new_value[:state] = new_value[:content].hash
            # Note: version is sync'd here, but don't rely upon property version with linked structures, but use structure's version method.
            new_value[:record][:version] = new_value[:content].version()
            if value.is_a?(::Hash)
              new_value[:record][:element] = "element_hash"
              new_value[:record][:element_hash_uuid] = new_value[:content].uuid.to_s
            else
              new_value[:record][:element] = "element_array"
              new_value[:record][:element_array_uuid] = new_value[:content].uuid.to_s
            end
          else
            # ### Persist Base Element Values
            new_value[:record][:element] = ::GxG::Database::Database::element_table_for_instance(value).to_s
            case new_value[:record][:element]
            when "element_boolean"
              case value.class
              when ::NilClass
                new_value[:record][:element_boolean] = -1
                new_value[:content] = nil
              when ::FalseClass
                new_value[:record][:element_boolean] = 0
                new_value[:content] = false
              when ::TrueClass
                new_value[:record][:element_boolean] = 1
                new_value[:content] = true
              end
            when "element_integer"
              new_value[:record][:element_integer] = value
              new_value[:content] = value
            when "element_float"
              new_value[:record][:element_float] = value
              new_value[:content] = value
            when "element_bigdecimal"
              new_value[:record][:element_bigdecimal] = ::BigDecimal.new(value.to_s)
              new_value[:content] = new_value[:record][:element_bigdecimal]
            when "element_datetime"
              new_value[:record][:element_datetime] = value
              new_value[:content] = value
            when "element_text"
              if value.size > 256
                # Note: be sure to keep text version & length sync'd with linked text element record
                if operation == :set_value
                  new_value[:record][:version] = @element_links[(indexer)][:record][:version]
                  new_value[:record][:element_text_uuid] = @element_links[(indexer)][:record][:element_text_uuid]
                end
                new_value[:record][:length] = value.size
              else
                new_value[:record][:element_text] = value
                new_value[:record][:length] = value.size
              end
              new_value[:content] = value
            when "element_binary"
              # Note: be sure to keep version & length sync'd with linked binary element record
              if operation == :set_value
                new_value[:record][:version] = @element_links[(indexer)][:record][:version]
                new_value[:record][:element_binary_uuid] = @element_links[(indexer)][:record][:element_binary_uuid]
              end
              new_value[:record][:length] = value.size
              new_value[:content] = value
            else
              raise Exception, "Unable to map an element type for value: #{value.inspect}"
            end
          end
        end
        # ### Commit Changes
        case operation
        when :set_value
          # Note: Set In-memory value only, don't save unless you have to.
          if new_value[:content].is_a?(@element_links[(indexer)][:content].class) || ([true, false, nil].include?(new_value[:content]) && [true, false, nil].include?(@element_links[(indexer)][:content]))
            # Replace value directly, but don't save yet unless you have to (:state refers to the last 'loaded-in-from-db' state of the data).
            new_value[:linkid] = @element_links[(indexer)][:linkid]
            if new_value[:content].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
              new_value[:record][:version] = new_value[:content].version()
            else
              new_value[:record][:version] = (((@element_links[(indexer)][:record][:version].to_f + 0.0001) * 10000.0).to_i.to_f / 10000.0)
            end
            new_value[:record][:ordinal] = @element_links[(indexer)][:record][:ordinal]
            new_value[:loaded] = true
            new_value[:state] = @element_links[(indexer)][:state]
            # ### Did string grow or shrink crossing the threshold??
            if new_value[:content].is_a?(::String)
              if (@element_links[(indexer)][:content].size > 256 && new_value[:content].size <= 256)
                # shrank - delete text object and pages as well as property record (slow)
                element_destroy(indexer)
                @element_links[(indexer)] = new_value
                element_write(indexer)
              else
                if (@element_links[(indexer)][:content].size <= 256 && new_value[:content].size > 256)
                  # grew - create text object and pages (a little less slow)
                  @element_links[(indexer)] = new_value
                  element_write(indexer)
                else
                  # N/A
                  @element_links[(indexer)] = new_value
                end
              end
            else
              # N/A
              @element_links[(indexer)] = new_value
            end
            if new_value[:content].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
              # Note: this ensures attachment to this object
              property_write(property_key)
            end
            #
          else
            # Other class value being substituted.
            if new_value[:content].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
              new_value[:record][:version] = new_value[:content].version()
            else
              new_value[:record][:version] = (((@element_links[(indexer)][:record][:version].to_f + 0.0001) * 10000.0).to_i.to_f / 10000.0)
            end
            new_value[:record][:ordinal] = @element_links[(indexer)][:record][:ordinal]
            new_value[:loaded] = true
            # Destroy old property record on db, and associated linked objects.
            # Review : this is slow - look into optimizations here.
            if @element_links[(indexer)][:content].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray, ::GxG::ByteArray, ::String)
              if @element_links[(indexer)][:content].is_a?(::String)
                if (@element_links[(indexer)][:content].size > 256 && new_value[:content].size <= 256) || (@element_links[(indexer)][:content].size <= 256 && new_value[:content].size > 256)
                  element_destroy(indexer)
                end
              else
                element_destroy(indexer)
              end
            end
            #
            @element_links[(indexer)] = new_value
            element_write(indexer)
          end
          #
        when :add_value
          # Note: set in-memory value and save.
          if new_value[:content].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
            new_value[:record][:version] = new_value[:content].version()
          else
            new_value[:record][:version] = 0.0
          end
          new_value[:record][:ordinal] = @element_links.size
          new_value[:loaded] = true
          #
          @element_links[(indexer)] = new_value
          # Review : is this wise to do this here??
          element_write(indexer)
        end
        # ### Handle coordination between persisted objects:
        if @element_links[(indexer)][:content].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
          # ### Extend Reservation to persisted objects ( Review : does this slow it down too much?? )
          @element_links[(indexer)][:content].release_reservation
          @db_address[:database].reservation_add_element((@reservation || @delegate), (@element_links[(indexer)][:content].db_address()[:table]), @element_links[(indexer)][:content].db_address()[:dbid])
          @element_links[(indexer)][:content].set_delegate((@reservation || @delegate))
          # ### Extend Permissions to persisted object
          @db_address[:database].extend_element_permissions(@db_address[:table],@db_address[:dbid],@element_links[(indexer)][:content].db_address()[:table],@element_links[(indexer)][:content].db_address()[:dbid])
          @db_address[:database].enforce_permission_policy({:action => :extend, :credential => @credential, :source => self, :destination => @element_links[(indexer)][:content]})
          #
          @element_links[(indexer)][:content].set_parent(self)
        end
        #
        self.increment_version()
        result = @element_links[(indexer)][:content]
        #
      else
        raise Exception, "You do not have sufficient privileges to make this change. (write-reservation)"
      end
    else
      raise Exception, "The value is not persistable."
    end
  else
    raise Exception, "You must provide a index in the form of an Integer."
  end
  result
end
alive?() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 773
def alive?()
  if @db_address
    if @db_address[:database].element_exists?(@db_address[:table],@db_address[:dbid])
      true
    else
      false
    end
  else
    false
  end
end
clear_constraint() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 602
def clear_constraint()
  if self.alive?
    if @constraint
      @constraint = nil
      @db_address[:database].connector()[:element_array].filter({:dbid => (@db_address[:dbid])}).update({:constraint => ""})
    end
  end
  true
end
constraint() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 612
def constraint()
  @constraint.clone
end
db_address() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 785
def db_address()
  @db_address
end
deactivate() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 789
def deactivate()
  if self.alive?()
    @element_links.each_index do |index|
      element = @element_links[(index)][:content]
      if element.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
        containers = [(element)]
        element.search({:include_inactive => false}) do |the_value, the_selector, the_container|
          if the_value.alive?
            the_value.deactivate
          end
          if the_container.alive?
            unless containers.include?(the_container)
                containers.unshift(the_container)
            end
          end
          nil
        end
        containers.each do |the_container|
          the_container.deactivate
        end
      end
    end
    if self.write_reserved?()
      self.release_reservation()
    end
    @element_links = []
    @db_address = nil
  end
  true
end
delete_at(indexer=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1244
def delete_at(indexer=nil)
  result = nil
  # if exists
  # if is not loaded, load element
  if self.alive?()
    if @db_address[:database].open?()
      if indexer.is_a?(::Integer)
        if self.write_reserved?()
          property_key = key.to_s.to_sym
          #
          if @element_links[(indexer)]
            # This will load the unloaded prior to separation.
            result = self[(indexer)]
            the_link = @element_links.delete_at(indexer)
            if the_link[:content].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
              the_link[:content].save
              the_link[:content].release_reservation()
              @db_address[:database].reservation_remove_element((@reservation || @delegate), the_link[:content].db_address()[:table], the_link[:content].db_address()[:dbid])
            else
              # Eliminate orphaned text and binary objects in the database. They will exist only in memory.
              if the_link[:content].is_any?(::String, ::GxG::ByteArray)
                if the_link[:content].is_a?(::String)
                  if the_link[:content].size > 256
                    # eliminate text object and pages.
                    the_temp_record = @db_address[:database].connector()[:element_text].select(:dbid).where({:uuid => the_link[:record][:element_text_uuid]}).first
                    if the_temp_record
                      @db_address[:database].element_destroy(@credential, :element_text, the_temp_record[:dbid])
                    end
                  end
                end
                if the_link[:content].is_a?(::GxG::ByteArray)
                  # eliminate binary object and pages.
                  the_temp_record = @db_address[:database].connector()[:element_binary].select(:dbid).where({:uuid => the_link[:record][:element_binary_uuid]}).first
                  if the_temp_record
                    @db_address[:database].element_destroy(@credential, :element_binary, the_temp_record[:dbid])
                  end
                end
              end
            end
            @db_address[:database].connector()[:array_elements].filter({:dbid => the_link[:linkid]}).delete
            refresh_ordinals
            self.increment_version()
          end
          #
        else
          raise Exception, "You do not have sufficient privileges to make this change"
        end
      else
        raise ArgumentError, "You must specify with a Symbol, not a #{key.class.inspect}"
      end
    else
      raise Exception, "Database not available"
    end
  else
    raise Exception, "Attempted to access a defunct structure"
  end
  result
end
destroy() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 847
def destroy()
  result = false
  if self.alive?
    begin
      unless self.write_reserved?()
        raise Exception, "You do not have a write-lock for this element"
      end
      unless @permission[:destroy]
        raise Exception, "You do not have permission to destory this element"
      end
      if @db_address[:database].open?()
        if @db_address[:database].element_in_use?(@db_address[:table], @db_address[:dbid])
          raise Exception, "Element is still linked to a structure.  Use <PersistedHash>.delete(<key>).destroy or <PersistedArray>.delete_at(<index>).destroy"
        else
          if self.write_reserved?()
            address = @db_address
            self.deactivate
            address[:database].element_destroy(@credential, address[:table],address[:dbid])
            # Review : consider either emptying the db trash now, or adding a flag to manifest records to prevent future loading.
            result = true
          else
            raise Exception, "You do not have sufficient privileges to make this change"
          end
        end
      else
        raise Exception, "Database not available"
      end
    rescue Exception => the_error
      log_error({:error => the_error})
    end
  end
  result
end
each(&block) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1432
def each(&block)
  if block.respond_to?(:call)
    load_element_links
    if @element_links.size > 0
      @element_links.each_index do |index|
        block.call(self[(index)])
      end
    end
    self
  else
    self.to_enum(:each)
  end
end
each_index(&block) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1446
def each_index(&block)
  if block.respond_to?(:call)
    load_element_links
    if @element_links.size > 0
      @element_links.each_index do |index|
        block.call(index)
      end
    end
    self
  else
    self.to_enum(:each_index)
  end
end
each_with_index(offset=0,&block) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1460
def each_with_index(offset=0,&block)
  if block.respond_to?(:call)
    load_element_links
    if @element_links.size > 0
      @element_links.to_enum(:each).with_index(offset).each do |entry, index|
        block.call(self[(index)], index)
      end
    end
    self
  else
    self.to_enum(:each_with_index,offset)
  end
end
element_version(index=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 526
def element_version(index=nil)
  result = 0.0
  if index.is_a?(::Numeric)
    if @element_links[(index)]
      result = @element_links[(index)][:record][:version]
    end
    #
  end
  result
end
export(options={:exclude_file_segments=>false}) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1347
def export(options={:exclude_file_segments=>false})
  if self.alive?
    exclude_file_segments = (options[:exclude_file_segments] || false)
    if options[:clone] == true
      # Review : why are cloned objects unconstrained? sync issues??
      result = {:type => :element_array, :uuid => GxG::uuid_generate.to_s.to_sym, :title => @title.clone, :version => @version.clone, :content => []}
    else
      result = {:type => :element_array, :uuid => @uuid.clone, :title => @title.clone, :version => @version.clone, :constraint => @constraint.clone, :content => []}
    end
    export_db = [{:parent => nil, :parent_selector => nil, :object => self, :record => result}]
    children_of = Proc.new do |the_parent=nil|
      list = []
      export_db.each do |node|
        if node[:parent].object_id == the_parent.object_id
          list << node
        end
      end
      list
    end
    # Build up export_db:
    self.search do |the_value, the_selector, the_container|
      if the_value.is_a?(::GxG::Database::PersistedHash)
        if options[:clone] == true
          the_uuid = GxG::uuid_generate.to_s.to_sym
        else
          the_uuid = the_value.uuid().clone
        end
        if (exclude_file_segments == true) && (the_selector == :file_segments || the_selector == :segments || the_selector == :portions)
          export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => {}, :record => {:type => :element_hash, :uuid => the_uuid, :title => the_value.title().clone, :version => the_value.version().clone, :format => the_value.format().clone, :content => {}}}
        else
          export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => {:type => :element_hash, :uuid => the_uuid, :title => the_value.title().clone, :version => the_value.version().clone, :format => the_value.format().clone, :content => {}}}
        end
      end
      if the_value.is_a?(::GxG::Database::PersistedArray)
        if options[:clone] == true
          the_uuid = GxG::uuid_generate.to_s.to_sym
        else
          the_uuid = the_value.uuid().clone
        end
        if (exclude_file_segments == true) && (the_selector == :file_segments || the_selector == :segments || the_selector == :portions)
          export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => [], :record => {:type => :element_array, :uuid => the_uuid, :title => the_value.title().clone, :version => the_value.version().clone, :constraint => the_value.constraint().clone, :content => []}}
        else
          export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => {:type => :element_array, :uuid => the_uuid, :title => the_value.title().clone, :version => the_value.version().clone, :constraint => the_value.constraint().clone, :content => []}}
        end
      end
      if the_value.is_any?(::GxG::Database::Database::valid_field_classes())
        data_type = GxG::Database::Database::element_table_for_instance(the_value)
        case data_type
        when :element_bigdecimal
          data = the_value.to_s
        when :element_datetime
          data = the_value.to_s
        when :element_binary
          data = the_value.to_s.encode64
        when :element_text
          data = the_value.to_s
        else
          data = the_value
        end              
        export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => {:type => data_type, :version => (the_container.version(the_selector) || 0.0), :content => data}}
      end
    end
    # Collect children export content:
    link_db = [(export_db[0])]
    while link_db.size > 0 do
      entry = link_db.shift
      children_of.call(entry[:object]).each do |the_child|
        entry[:record][:content][(the_child[:parent_selector])] = the_child[:record]
        if the_child[:object].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
          link_db << the_child
        end
      end
    end
  else
    result = nil
  end
  result
end
find_index(the_value) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1336
def find_index(the_value)
  result = nil
  @element_links.each_with_index do |element, indexer|
    if element[:content] == the_value
      result = indexer
      break
    end
  end
  result
end
get_at_path(the_path="/") click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1633
def get_at_path(the_path="/")
  # /^(?:[0-9])*[0-9](?:[0-9])*$/ = nil if an alpha present there, else 0 only numeric
  # Attribution : http://stackoverflow.com/questions/1240674/regex-match-a-string-containing-numbers-and-letters-but-not-a-string-of-just-nu
  #
  # if ":" detected do: (str.gsub("%2f","/").to_sym) as key else (str.gsub("%2f","/"))
  result = nil
  if the_path == "/"
    result = self
  else
    object_stack = [(self)]
    path_stack = the_path.split("/")
    path_stack.to_enum.each do |path_element|
      element = nil
      if path_element.size > 0
        if (path_element =~ /^(?:[0-9])*[0-9](?:[0-9])*$/) == 0
          element = path_element.to_i
        else
          element = path_element
          element.gsub!("%2f","/")
          if element[0] == ":"
            element = element[(1..-1)].to_sym
          end
        end
      end
      if element
        result = object_stack.first[(element)]
        if result.is_a?(NilClass)
          break
        else
          object_stack.unshift(result)
        end
      else
        # ignore double slashes? '//'
        # break
      end
    end
  end
  result
end
get_delegate() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 496
def get_delegate()
  if self.alive?
    if @delegate.is_any?(::String, ::Symbol)
      @delegate.clone
    end
  end
end
get_permissions() click to toggle source

Permission Management:

# File lib/gxg/gxg_database_persistedarray.rb, line 321
def get_permissions()
  @permission.clone
end
get_reservation() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 424
def get_reservation()
  result = false
  # Review : Experimental design change - deprecate @delegate use, require entire structure (and sub-structures) to get solid @reservation (all of them) or this fails.
  # Note : keep your structures small as this opens the door for stack-depth exceptions if it is nested too deep. (say 256 or less layers deep??)
  if @reservation
    result = true
  else
    if self.alive?
      if @permission[:write]
        clean_up_list = []
        # Review : efficiency - write locks only apply to PersistedHashes and PersistedArrays so do we need a full manifest??
        the_reservation = @db_address[:database].reserve_element_locks(@credential, (@db_address[:database].element_manifest(@db_address[:table], @db_address[:dbid])), :write)
        if the_reservation
          @element_links.each_index do |ordinal|
            if @element_links[(ordinal)][:content].is_any?([::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray])
              clean_up_list << @element_links[(ordinal)][:content]
              unless @element_links[(ordinal)][:content].get_reservation()
                @db_address[:database].release_element_locks(the_reservation)
                the_reservation = nil
                break
              end
            end
          end
          #
        end
        if the_reservation
          @reservation = the_reservation
          result = true
        else
          clean_up_list.each do |the_object|
            the_object.release_reservation
          end
        end
      end
    end
  end
  # xxx keep old code for now
  # if (@reservation || @delegate)
  #   result = true
  # else
  #   if self.alive?
  #     if @permission[:write]
  #       @reservation = @db_address[:database].reserve_element_locks(@credential, (@db_address[:database].element_manifest(@db_address[:table], @db_address[:dbid])), :write)
  #       if @reservation
  #         @element_links.each_index do |ordinal|
  #           if @element_links[(ordinal)][:content].is_any?([::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray])
  #             @element_links[(ordinal)][:content].set_delegate((@reservation || @delegate))
  #           end
  #         end
  #         result = true
  #       end
  #       #
  #     end
  #   end
  # end
  # xxx end old code
  result
end
include?(the_value) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1325
def include?(the_value)
  result = false
  @element_links.each do |element|
    if element[:content] == the_value
      result = true
      break
    end
  end
  result
end
increment_version() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 552
def increment_version()
  if self.alive?
    if @db_address[:database].open?
      if self.write_reserved?()
        @version = (((@version + 0.0001) * 10000.0).to_i.to_f / 10000.0)
      end
    end
  end
end
inspect() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 746
def inspect()
  # FORNOW: make re-entrant (yes, I know!) Fortunately, circular links are impossible with PersistedArray.
  # TODO: make interative instead of re-entrant.
  result = "(Not Loaded)"
  if @db_address
    if @db_address[:database].element_byte_size(@db_address[:table], @db_address[:dbid]) <= 10485760
      # smaller than 10MB
      result = "["
      @element_links.each_index do |element_index|
        if @element_links[(element_index)].is_a?(::Hash)
          result << @element_links[(element_index)][:content].inspect
        else
          result << "(Not Loaded)"
        end
        unless element_index == (@element_links.size - 1)
          result << ", "
        end
      end
      result << "]"
    else
      result = "(Too Damned Big)"
    end
    #
  end
  result
end
iterative(options={:include_inactive => true}, &block) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1474
def iterative(options={:include_inactive => true}, &block)
  result = []
  visit = Proc.new do |the_node=nil, accumulator=[]|
    node_stack = []
    if the_node
      node_stack << ({:parent => nil, :parent_selector => nil, :object => (the_node)})
      while (node_stack.size > 0) do
        a_node = node_stack.shift
        #
        if a_node[:object].is_a?(::GxG::Database::PersistedHash)
          if a_node[:object].alive?
            a_node[:object].each_pair do |the_key, the_value|
              node_stack << ({:parent => a_node[:object], :parent_selector => the_key, :object => the_value})
            end
          else
            if options[:include_inactive]
              accumulator << a_node
            end
          end
        end
        if a_node[:object].is_a?(::GxG::Database::PersistedArray)
          if a_node[:object].alive?
            a_node[:object].each_with_index do |the_value, the_index|
              node_stack << ({:parent => a_node[:object], :parent_selector => the_index, :object => the_value})
            end
          else
            if options[:include_inactive]
              accumulator << a_node
            end
          end
        end
        #
        if a_node.alive? || options[:include_inactive]
          accumulator << a_node
        end
      end
    end
    accumulator
  end
  #
  children_of = Proc.new do |the_db=[], the_parent=nil|
    list = []
    the_db.each do |node|
      if node[:parent].object_id == the_parent.object_id
        list << node
      end
    end
    list
  end
  #
  begin
    database = visit.call(self,[])
    link_db = children_of.call(database, self)
    if block.respond_to?(:call)
      while (link_db.size > 0) do
        entry = link_db.shift
        unless entry[:object].object_id == self.object_id
          # calls with parameters: the_value, the_key/the_index (the_selector), the_container
          raw_result = block.call(entry[:object], entry[:parent_selector], entry[:parent])
          if raw_result
            result << raw_result
          end
        end
        if entry[:object].object_id != nil.object_id
          children = children_of.call(database, entry[:object])
          children.each do |child|
            link_db << child
          end
        end
      end
    end
    #
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {}})
  end
  #
  result
end
parent() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 629
def parent()
  @parent
end
paths_to(the_object=nil,base_path="") click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1566
def paths_to(the_object=nil,base_path="")
  # new idea here:
  search_results = []
  unless base_path[0] == "/"
    base_path = ("/" << base_path)
  end
  if base_path.size > 1
    path_stack = base_path.split("/")[1..-1].reverse
  else
    path_stack = []
  end
  origin = self.get_at_path(base_path)
  container_stack = [{:selector => nil, :container => origin}]
  find_container = Proc.new do |the_container|
    result = nil
    container_stack.each_with_index do |entry, index|
      if entry[:container] == the_container
        result = entry
        break
      end
    end
    result
  end
  last_container = origin
  found = false
  # tester = {:a=>1, :b=>2, :c=>[0, 5], :testing=>{:d=>4.0, :e=>0.9, :f => nil}}
  if origin.is_any?(::Hash, ::Array, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
    origin.process! do |the_value, selector, container|
      if last_container.object_id != container.object_id
        container_record = find_container.call(container)
        if container_record
          path_stack = container_record[:prefix].split("/").reverse
          if path_stack.size == 0
            path_stack << ""
          end
        end
        last_container = container
      end
      if selector.is_a?(Symbol)
        safe_key = (":" + selector.to_s)
      else
        safe_key = selector.to_s
      end
      safe_key.gsub!("/","%2f")
      path_stack.unshift(safe_key)
      # compare the_value
      found = false
      if (the_value == the_object)
        found = true
      end
      if found
        search_results << ("/" << path_stack.reverse.join("/"))
      end
      #
      if the_value.is_any?(::Array, ::Hash, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
        container_stack.unshift({:selector => selector, :container => the_value, :prefix => (path_stack.reverse.join("/"))})
      end
      path_stack.shift
      #
      nil
    end
  else
    search_results << ("/" << path_stack.join("/"))
  end
  search_results
end
pop() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1321
def pop()
  self.delete_at((@element_links.size - 1))
end
process!(options={:include_inactive => true}, &block) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1553
def process!(options={:include_inactive => true}, &block)
  self.iterative(options, &block)
  self
end
push(*args) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1312
def push(*args)
  if args.size > 0
    args.each do |item|
      self << item
    end
  end
  self
end
release_reservation() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 405
def release_reservation()
  if self.alive?()
    if @reservation
      @db_address[:database].release_element_locks(@reservation)
      @reservation = nil
    end
    if @delegate
      @delegate = nil
    end
    # release write-locks of all sub-items
    @element_links.each_index do |ordinal|
      if @element_links[(ordinal)][:content].is_any?([::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray])
        @element_links[(ordinal)][:content].release_reservation
      end
    end
  end
  true
end
reservation() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 385
def reservation()
  if self.alive?
    if @reservation.is_any?(::String, ::Symbol)
      @reservation.clone
    end
  end
end
save() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 820
def save()
  result = false
  if self.alive?
    begin
      if @db_address[:database].open?()
        @element_links.each_index do |index|
          # Note: only save property data and header if: a) data is still loaded and b) state has changed.
          if @element_links[(index)][:loaded] == true
            if @element_links[(index)][:state] != @element_links[(index)][:content].hash
              @element_links[(index)][:record][:version] = (((@element_links[(index)][:record][:version].to_f + 0.0001) * 10000.0).to_i.to_f / 10000.0)
              element_write(index)
            end
          end
          #
        end
      else
        raise Exception, "Database not available"
      end
      self.save_version
      result = true
    rescue Exception => the_error
      log_error({:error => the_error})
    end
  end
  result
end
save_version() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 562
def save_version()
  @db_address[:database].connector()[:element_array].filter({:dbid => @db_address[:dbid]}).update({:version => @version})
end
set_at_path(the_path="/",the_value=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1673
def set_at_path(the_path="/",the_value=nil)
  result = nil
  if the_path != "/"
    container = self.get_at_path(::File::dirname(the_path))
    if container
      raw_selector = ::File::basename(the_path)
      selector = nil
      if raw_selector.size > 0
        if (raw_selector =~ /^(?:[0-9])*[0-9](?:[0-9])*$/) == 0
          selector = raw_selector.to_i
        else
          selector = raw_selector
          selector.gsub!("%2f","/")
          if selector[0] == ":"
            selector = selector[(1..-1)].to_sym
          end
        end
      end
      if selector
        container[(selector)] = the_value
        result = container[(selector)]
      else
        # ignore double slashes? '//'
        # break
      end
      #
    end
  end
  result
end
set_constraint(format_uuid=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 591
def set_constraint(format_uuid=nil)
  if self.alive?
    unless @constraint
      if ::GxG::valid_uuid?(format_uuid)
        @constraint = format_uuid.to_sym
        @db_address[:database].connector()[:element_array].filter({:dbid => (@db_address[:dbid])}).update({:constraint => (@constraint.to_s)})
      end
    end
  end
end
set_delegate(the_delegate=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 504
def set_delegate(the_delegate=nil)
  if self.alive?
    if the_delegate.is_any?([::String, ::Symbol])
      @delegate = the_delegate.to_sym
    end
  end
end
set_element_version(element_index, the_version=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 537
def set_element_version(element_index, the_version=nil)
  result = false
  if @element_links[(element_index)]
    if the_version.is_a?(::Numeric)
      @element_links[(element_index)][:record][:version] = (((the_version.to_f) * 10000.0).to_i.to_f / 10000.0)
      result = true
    else
      log_warning("Attempted to set version to an invalid version value #{the_version.inspect} for index #{element_index.inspect} on Object #{@uuid.inspect}")
    end
  else
    log_warning("Attempted to set version with an invalid index #{element_index.inspect} on Object #{@uuid.inspect}")
  end
  result
end
set_parent(object=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 633
def set_parent(object=nil)
  if self.alive?
    if object.is_any?([::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray])
      unless @parent
        @parent = object
      end
    end
  end
end
set_permissions(credential=nil, the_permission=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 325
def set_permissions(credential=nil, the_permission=nil)
  if self.alive?
    if credential.is_a?(::Hash) && the_permission.is_a?(::Hash)
      if credential[:user]
        if credential[:user] == "public" || credential[:user] == "Public"
          credential = "00000000-0000-4000-0000-000000000000"
        else
          credential = (@db_address[:database].user_fetch({:user_id => credential[:user].to_s}) || {})[:uuid]
        end
        if credential
          credential = credential.to_s.to_sym
        end
      else
        if credential[:group]
          credential = @db_address[:database].group_credential(credential)
        else
          credential = nil
        end
      end
    else
      if credential.is_a?(::Hash) && the_permission == nil
        the_permission = credential
        credential = @credential
      else
        unless credential
          credential = @credential
        end
      end
    end
    if the_permission.is_a?(::Hash) && ::GxG::valid_uuid?(credential)
      manifest = []
      structures = [{:table => @db_address[:table], :dbid => @db_address[:dbid]}]
      while structures.size > 0 do
        entry = structures[0]
        @db_address[:database].element_manifest(entry[:table],entry[:dbid]).each do |record|
          if [:element_hash, :element_array].include?(record[:table])
            unless structures.include?(record)
              structures << record
            end
          else
            # Review - only set/get/check permissions on persisted arrays/hashes
            # unless manifest.include?(record)
            #   manifest << record
            # end
          end
        end
        manifest << structures.shift
      end
      manifest.each do |entry|
        @db_address[:database].assign_element_permission(entry[:table], entry[:dbid], credential, the_permission)
      end
      #
      true
    else
      log_error({:error => Exception.new("You MUST provide a valid permissions Hash."), :parameters => {:credential => credential, :permission => the_permission}})
      false
    end
  end
end
set_title(the_title=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 577
def set_title(the_title=nil)
  if self.alive?
    if @db_address[:database].open?
      if self.write_reserved?()
        if the_title
          @title = the_title.to_s[0..256]
          @db_address[:database].connector()[:element_array].filter({:dbid => @db_address[:dbid]}).update({:title => @title})
          self.increment_version
        end
      end
    end
  end
end
set_version(the_version=0.0) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 566
def set_version(the_version=0.0)
  if self.write_reserved?()
    @version = (((the_version.to_f) * 10000.0).to_i.to_f / 10000.0)
    self.save_version
  end
end
size() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 881
def size()
  @element_links.size
end
structure_attached?() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 885
def structure_attached?()
  @db_address[:database].structure_attached?(@uuid.to_s)
end
structure_detach() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 888
def structure_detach()
  @db_address[:database].structure_detach(@uuid.to_s)
end
sync_export(options={}) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1426
def sync_export(options={})
  # Review : does this work with PersistedArray ??
  self.save
  @db_address[:database].sync_export(@credential, [(@uuid)], options)
end
title() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 573
def title()
  @title.clone
end
ufs() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 616
def ufs()
  if @constraint
    record = @db_address[:database].format_load({:uuid => @constraint.to_s})
    if record
      record[:ufs]
    else
      ""
    end
  else
    ""
  end
end
unload(indexer=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1174
def unload(indexer=nil)
  result = false
  # if key exists
  # if key is loaded, unload element (if String or ByteArray)
  if self.alive?()
    if @db_address[:database].open?()
      if indexer.is_a?(::Integer)
        if @element_links[(indexer)]
          if @element_links[(indexer)][:content].is_any?(::String, ::GxG::ByteArray)
            if @element_links[(indexer)][:loaded] == true
              # ### Unload Base Element contents from memory, leaving reference harness intact and active.
              @element_links[(indexer)][:content].clear
              @element_links[(indexer)][:loaded] = false
            end
          end
          result = true
        end
      else
        raise ArgumentError, "You must specify with an Integer, not a #{indexer.class.inspect}"
      end
    else
      raise Exception, "Database not available"
    end
  else
    raise Exception, "Attempted to access a defunct structure"
  end
  result
end
unpersist() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 1704
def unpersist()
  result = []
  if self.alive?
    #
    export_db = [{:parent => nil, :parent_selector => nil, :object => self, :record => result}]
    children_of = Proc.new do |the_parent=nil|
      list = []
      export_db.each do |node|
        if node[:parent].object_id == the_parent.object_id
          list << node
        end
      end
      list
    end
    # Build up export_db:
    self.search do |the_value, the_selector, the_container|
      if the_value.is_a?(::GxG::Database::PersistedHash)
        export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => {}}
      else
        if the_value.is_a?(::GxG::Database::PersistedArray)
          export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => []}
        else
          export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => the_value}
        end
      end
    end
    # Collect children export content:
    link_db =[(export_db[0])]
    while link_db.size > 0 do
      entry = link_db.shift
      children_of.call(entry[:object]).each do |the_child|
        entry[:record][(the_child[:parent_selector])] = the_child[:record]
        if the_child[:object].is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
          link_db << the_child
        end
      end
    end
    #
  end
  result
end
uuid() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 512
def uuid()
  @uuid.clone
end
version(input=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 516
def version(input=nil)
  @version.clone
end
version=(the_version=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 520
def version=(the_version=nil)
  if the_version.is_a?(::Numeric)
    @version = (((the_version.to_f) * 10000.0).to_i.to_f / 10000.0)
  end
end
wait_for_reservation(timeout=nil) click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 483
def wait_for_reservation(timeout=nil)
  result = true
  the_timeout = Time.now.to_f + (timeout || 30.0).to_f
  until self.get_reservation() == true do
    sleep 1.0
    if Time.now.to_f >= the_timeout
      result = false
      break
    end
  end
  result
end
write_permission?() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 393
def write_permission?()
  @permission[:write]
end
write_reserved?() click to toggle source
# File lib/gxg/gxg_database_persistedarray.rb, line 397
def write_reserved?()
  if @reservation or @delegate
    true
  else
    false
  end
end