# = ormsupport.rb
#
# == Copyright (c) 2004 George Moschovitis, Thomas Sawyer
#
#   Ruby License
#
#   This module is free software. You may use, modify, and/or redistribute this
#   software under the same terms as Ruby.
#
#   This program is distributed in the hope that it will be useful, but WITHOUT
#   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
#   FOR A PARTICULAR PURPOSE.
#
# == Special Thanks
#
# Big thanks to DHH and Rails.
#
# == Author(s)
#
# * George Moschovitis
# * Thomas Sawyer

# Author::    George Moschovitis, Thomas Sawyer
# Copyright:: Copyright (c) 2005 George Moschovitis, Thomas Sawyer
# License::   Ruby License

require 'facets/core/inflect'

require 'facets/core/module/attr_setter'
require 'facets/core/module/basename'
require 'facets/core/string/to_const'

# = ORMSupport
#
# Provides a number of basc convenience methods for working with Object
# Relational Mapping.

module ORMSupport

  #++
  # class level
  #--

  def self.default_system(s="~".to_sym)
    unless s == "~".to_sym
      @default_system = x.to_sym
    else
      @default_system ||= :og
    end
  end

  def self.default_key(k="~".to_sym)
    unless k == "~".to_sym
      @default_key = k.to_s
    else
      @default_key ||= '_id'
    end
  end

  #++
  # instance level
  #--

  # Converts a class-esque name into a table name.
  def tablename( sys=:og )
    sys ||= ORMSupport.default_system
    case sys.to_sym
    when :rails, :ar, :activerecord
      to_s.underscore.plural
    when :nitro, :og
      to_s.gsub(/::/, '_').downcase
    else
      to_s.gsub(/::/, '_').downcase
    end
  end
  alias_method :table_name, :tablename  # a la Rails
  alias_method :tableize,   :tablename    # a la Rails

  # Converts a table name into a class name.
  #--
  # Should this return the calculated name even if the class isn't found?
  #++
  def classname( sys=nil )
    sys ||= ORMSupport.default_system
    case sys.to_sym
    when :rails, :ar, :activerecord
      cn = to_s.singular.camelize
    when :nitro, :og
      cn = to_s.gsub(/_/, '::').camelize
    else
      cn = to_s.gsub(/_/, '::').camelize
    end
    k = findclass( cn )
    return k.name if k
    return cn
  end
  alias_method :class_name, :classname  # a la Rails

  # Like classname, but returns the actual class.
  #--
  # TODO Error if not found?
  #++
  def classify( sys=:og )
    findclass( classname( sys ) )
  end

  def findclass( str )
    str = str.gsub(/^::/,'')
    k = nil
    ObjectSpace.each_object(Class) { |c| (k = c;  break) if c.name.downcase == str.downcase }
    return k
  end
  private :findclass


  # This is good for generating database key/id field names from class names.
  # In essense, it demodulizes, underscores and appends 'id'.
  def keyname( key=nil )
    key ||= ORMSupport.default_key
    case key.to_sym
    when :_id
      self.basename.underscore + "_id"
    when :id
      self.basename.underscore + "id"
    when :_key
      self.basename.underscore + "_key"
    when :key
      self.basename.underscore + "key"
    else
      self.basename.underscore + ORMSupport.default_key
    end
  end
  alias_method :key_name, :keyname     # to be consistant
  alias_method :foreign_key, :keyname  # a la Rails

end

#--

class String
  include ORMSupport
end

class Class
  include ORMSupport
  alias_method :demodulize, :basename  # a la Rails
end

#++



#  _____         _
# |_   _|__  ___| |_
#   | |/ _ \/ __| __|
#   | |  __/\__ \ |_
#   |_|\___||___/\__|
#

=begin #testing

  require 'test/unit'

  # fixtures

  class Vendor
  end

  module MockMod
    class Customer
    end
  end

  # test

  class TC_ORMSupport < Test::Unit::TestCase

    # tablename

    def test_tablename
      assert_equal( 'vendor', "Vendor".tablename )
      assert_equal( 'mockmod_customer', "MockMod::Customer".tablename )
    end

    # tableize

    def test_tableize
      assert_equal( 'vendor', "Vendor".tableize )
      assert_equal( 'mockmod_customer', "MockMod::Customer".tableize )
    end

    # classname

    def test_classname
      assert_equal( 'Vendor', "vendor".classname )
      assert_equal( 'MockMod::Customer', "mockmod_customer".classname, :none )
    end

    # classify

    def test_classify
      assert_equal( Vendor, "vendor".classify )
      assert_equal( MockMod::Customer, "mockmod_customer".classify )
    end

    # keyname

    def test_keyname
      assert_equal( 'vendor_id', "Vendor".keyname )
      assert_equal( 'customer_id', "MockMod::Customer".keyname )
      assert_equal( 'customerid', "MockMod::Customer".keyname( :id ) )
    end

    # foriegn_key (same as keyname)

    def test_foriegn_key
      assert_equal( 'vendor_id', "Vendor".foreign_key )
      assert_equal( 'customer_id', "MockMod::Customer".foreign_key )
      assert_equal( 'customerid', "MockMod::Customer".foreign_key( :id ) )
    end

  end

=end
