activefacts 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
 - data/Manifest.txt +83 -0
 - data/README.rdoc +81 -0
 - data/Rakefile +41 -0
 - data/bin/afgen +46 -0
 - data/bin/cql +52 -0
 - data/examples/CQL/Address.cql +46 -0
 - data/examples/CQL/Blog.cql +54 -0
 - data/examples/CQL/CompanyDirectorEmployee.cql +51 -0
 - data/examples/CQL/Death.cql +16 -0
 - data/examples/CQL/Genealogy.cql +95 -0
 - data/examples/CQL/Marriage.cql +18 -0
 - data/examples/CQL/Metamodel.cql +238 -0
 - data/examples/CQL/MultiInheritance.cql +19 -0
 - data/examples/CQL/OilSupply.cql +47 -0
 - data/examples/CQL/Orienteering.cql +108 -0
 - data/examples/CQL/PersonPlaysGame.cql +17 -0
 - data/examples/CQL/SchoolActivities.cql +31 -0
 - data/examples/CQL/SimplestUnary.cql +12 -0
 - data/examples/CQL/SubtypePI.cql +32 -0
 - data/examples/CQL/Warehousing.cql +99 -0
 - data/examples/CQL/WindowInRoomInBldg.cql +22 -0
 - data/lib/activefacts.rb +10 -0
 - data/lib/activefacts/api.rb +25 -0
 - data/lib/activefacts/api/concept.rb +384 -0
 - data/lib/activefacts/api/constellation.rb +106 -0
 - data/lib/activefacts/api/entity.rb +239 -0
 - data/lib/activefacts/api/instance.rb +54 -0
 - data/lib/activefacts/api/numeric.rb +158 -0
 - data/lib/activefacts/api/role.rb +94 -0
 - data/lib/activefacts/api/standard_types.rb +67 -0
 - data/lib/activefacts/api/support.rb +59 -0
 - data/lib/activefacts/api/value.rb +122 -0
 - data/lib/activefacts/api/vocabulary.rb +120 -0
 - data/lib/activefacts/cql.rb +31 -0
 - data/lib/activefacts/cql/CQLParser.treetop +104 -0
 - data/lib/activefacts/cql/Concepts.treetop +112 -0
 - data/lib/activefacts/cql/DataTypes.treetop +66 -0
 - data/lib/activefacts/cql/Expressions.treetop +113 -0
 - data/lib/activefacts/cql/FactTypes.treetop +185 -0
 - data/lib/activefacts/cql/Language/English.treetop +92 -0
 - data/lib/activefacts/cql/LexicalRules.treetop +169 -0
 - data/lib/activefacts/cql/Rakefile +6 -0
 - data/lib/activefacts/cql/parser.rb +88 -0
 - data/lib/activefacts/generate/absorption.rb +87 -0
 - data/lib/activefacts/generate/cql.rb +441 -0
 - data/lib/activefacts/generate/cql/html.rb +397 -0
 - data/lib/activefacts/generate/null.rb +19 -0
 - data/lib/activefacts/generate/ordered.rb +557 -0
 - data/lib/activefacts/generate/ruby.rb +326 -0
 - data/lib/activefacts/generate/sql/server.rb +164 -0
 - data/lib/activefacts/generate/text.rb +21 -0
 - data/lib/activefacts/input/cql.rb +1268 -0
 - data/lib/activefacts/input/orm.rb +926 -0
 - data/lib/activefacts/persistence.rb +1 -0
 - data/lib/activefacts/persistence/composition.rb +653 -0
 - data/lib/activefacts/support.rb +51 -0
 - data/lib/activefacts/version.rb +3 -0
 - data/lib/activefacts/vocabulary.rb +6 -0
 - data/lib/activefacts/vocabulary/extensions.rb +343 -0
 - data/lib/activefacts/vocabulary/metamodel.rb +303 -0
 - data/script/txt2html +71 -0
 - data/spec/absorption_spec.rb +95 -0
 - data/spec/api/autocounter.rb +82 -0
 - data/spec/api/constellation.rb +130 -0
 - data/spec/api/entity_type.rb +101 -0
 - data/spec/api/instance.rb +428 -0
 - data/spec/api/roles.rb +122 -0
 - data/spec/api/value_type.rb +112 -0
 - data/spec/api_spec.rb +14 -0
 - data/spec/cql_cql_spec.rb +58 -0
 - data/spec/cql_parse_spec.rb +31 -0
 - data/spec/cql_ruby_spec.rb +60 -0
 - data/spec/cql_sql_spec.rb +54 -0
 - data/spec/cql_symbol_tables_spec.rb +259 -0
 - data/spec/cql_unit_spec.rb +336 -0
 - data/spec/cqldump_spec.rb +169 -0
 - data/spec/norma_cql_spec.rb +48 -0
 - data/spec/norma_ruby_spec.rb +50 -0
 - data/spec/norma_sql_spec.rb +45 -0
 - data/spec/norma_tables_spec.rb +94 -0
 - data/spec/spec.opts +1 -0
 - data/spec/spec_helper.rb +10 -0
 - metadata +173 -0
 
    
        data/script/txt2html
    ADDED
    
    | 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            load File.dirname(__FILE__) + "/../Rakefile"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rubyforge'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'redcloth'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'syntax/convertors/html'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'erb'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            download = "http://rubyforge.org/projects/#{$hoe.rubyforge_name}"
         
     | 
| 
      
 10 
     | 
    
         
            +
            version  = $hoe.version
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            def rubyforge_project_id
         
     | 
| 
      
 13 
     | 
    
         
            +
              RubyForge.new.configure.autoconfig["group_ids"][$hoe.rubyforge_name]
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            class Fixnum
         
     | 
| 
      
 17 
     | 
    
         
            +
              def ordinal
         
     | 
| 
      
 18 
     | 
    
         
            +
                # teens
         
     | 
| 
      
 19 
     | 
    
         
            +
                return 'th' if (10..19).include?(self % 100)
         
     | 
| 
      
 20 
     | 
    
         
            +
                # others
         
     | 
| 
      
 21 
     | 
    
         
            +
                case self % 10
         
     | 
| 
      
 22 
     | 
    
         
            +
                when 1: return 'st'
         
     | 
| 
      
 23 
     | 
    
         
            +
                when 2: return 'nd'
         
     | 
| 
      
 24 
     | 
    
         
            +
                when 3: return 'rd'
         
     | 
| 
      
 25 
     | 
    
         
            +
                else    return 'th'
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            class Time
         
     | 
| 
      
 31 
     | 
    
         
            +
              def pretty
         
     | 
| 
      
 32 
     | 
    
         
            +
                return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            def convert_syntax(syntax, source)
         
     | 
| 
      
 37 
     | 
    
         
            +
              return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            if ARGV.length >= 1
         
     | 
| 
      
 41 
     | 
    
         
            +
              src, template = ARGV
         
     | 
| 
      
 42 
     | 
    
         
            +
              template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
         
     | 
| 
      
 43 
     | 
    
         
            +
            else
         
     | 
| 
      
 44 
     | 
    
         
            +
              puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
         
     | 
| 
      
 45 
     | 
    
         
            +
              exit!
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            template = ERB.new(File.open(template).read)
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            title = nil
         
     | 
| 
      
 51 
     | 
    
         
            +
            body = nil
         
     | 
| 
      
 52 
     | 
    
         
            +
            File.open(src) do |fsrc|
         
     | 
| 
      
 53 
     | 
    
         
            +
              title_text = fsrc.readline
         
     | 
| 
      
 54 
     | 
    
         
            +
              body_text_template = fsrc.read
         
     | 
| 
      
 55 
     | 
    
         
            +
              body_text = ERB.new(body_text_template).result(binding)
         
     | 
| 
      
 56 
     | 
    
         
            +
              syntax_items = []
         
     | 
| 
      
 57 
     | 
    
         
            +
              body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
         
     | 
| 
      
 58 
     | 
    
         
            +
                ident = syntax_items.length
         
     | 
| 
      
 59 
     | 
    
         
            +
                element, syntax, source = $1, $2, $3
         
     | 
| 
      
 60 
     | 
    
         
            +
                syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
         
     | 
| 
      
 61 
     | 
    
         
            +
                "syntax-temp-#{ident}"
         
     | 
| 
      
 62 
     | 
    
         
            +
              }
         
     | 
| 
      
 63 
     | 
    
         
            +
              title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
         
     | 
| 
      
 64 
     | 
    
         
            +
              body = RedCloth.new(body_text).to_html
         
     | 
| 
      
 65 
     | 
    
         
            +
              body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
      
 67 
     | 
    
         
            +
            stat = File.stat(src)
         
     | 
| 
      
 68 
     | 
    
         
            +
            created = stat.ctime
         
     | 
| 
      
 69 
     | 
    
         
            +
            modified = stat.mtime
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            $stdout << template.result(binding)
         
     | 
| 
         @@ -0,0 +1,95 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # ActiveFacts tests: Test the relational absorption by compiling CQL fragments.
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'treetop'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'activefacts/support'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'activefacts/api/support'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'activefacts/input/cql'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'activefacts/persistence'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            describe "Absorption" do
         
     | 
| 
      
 13 
     | 
    
         
            +
              Prologue = %Q{
         
     | 
| 
      
 14 
     | 
    
         
            +
                vocabulary Test;
         
     | 
| 
      
 15 
     | 
    
         
            +
                DateTime is defined as DateAndTime();
         
     | 
| 
      
 16 
     | 
    
         
            +
                Month is defined as VariableLengthText(3);
         
     | 
| 
      
 17 
     | 
    
         
            +
                Season is defined as VariableLengthText(6);
         
     | 
| 
      
 18 
     | 
    
         
            +
                PartyID is defined as AutoCounter();
         
     | 
| 
      
 19 
     | 
    
         
            +
                ClaimID is defined as AutoCounter();
         
     | 
| 
      
 20 
     | 
    
         
            +
              }
         
     | 
| 
      
 21 
     | 
    
         
            +
              Claim = %Q{
         
     | 
| 
      
 22 
     | 
    
         
            +
                Claim is identified by ClaimID where
         
     | 
| 
      
 23 
     | 
    
         
            +
                  Claim has exactly one ClaimID,
         
     | 
| 
      
 24 
     | 
    
         
            +
                  ClaimID is of at most one Claim;
         
     | 
| 
      
 25 
     | 
    
         
            +
              }
         
     | 
| 
      
 26 
     | 
    
         
            +
              Incident = %Q{
         
     | 
| 
      
 27 
     | 
    
         
            +
                Incident is identified by Claim where
         
     | 
| 
      
 28 
     | 
    
         
            +
                  Claim concerns at most one Incident,
         
     | 
| 
      
 29 
     | 
    
         
            +
                  Incident is of exactly one Claim;
         
     | 
| 
      
 30 
     | 
    
         
            +
              }
         
     | 
| 
      
 31 
     | 
    
         
            +
              Party = %Q{
         
     | 
| 
      
 32 
     | 
    
         
            +
                Party is identified by PartyID where
         
     | 
| 
      
 33 
     | 
    
         
            +
                  Party has exactly one PartyID,
         
     | 
| 
      
 34 
     | 
    
         
            +
                  PartyID is of at most one Party;
         
     | 
| 
      
 35 
     | 
    
         
            +
              }
         
     | 
| 
      
 36 
     | 
    
         
            +
              Person = %Q{
         
     | 
| 
      
 37 
     | 
    
         
            +
                Person is a kind of Party;
         
     | 
| 
      
 38 
     | 
    
         
            +
              }
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              Tests = [
         
     | 
| 
      
 41 
     | 
    
         
            +
                { :should => "inject a value column into the table for an independent ValueType",
         
     | 
| 
      
 42 
     | 
    
         
            +
                  :cql => %Q{
         
     | 
| 
      
 43 
     | 
    
         
            +
                    #{Prologue}
         
     | 
| 
      
 44 
     | 
    
         
            +
                    Month is in exactly one Season;
         
     | 
| 
      
 45 
     | 
    
         
            +
                  },
         
     | 
| 
      
 46 
     | 
    
         
            +
                  :tables => { "Month" => [ %w{Month Value}, "Season" ] }
         
     | 
| 
      
 47 
     | 
    
         
            +
                },
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                { :should => "absorb a one-to-one along the identification path",
         
     | 
| 
      
 50 
     | 
    
         
            +
                  :cql => %Q{
         
     | 
| 
      
 51 
     | 
    
         
            +
                    #{Prologue} #{Claim} #{Incident}
         
     | 
| 
      
 52 
     | 
    
         
            +
                    Incident relates to loss on exactly one DateTime;
         
     | 
| 
      
 53 
     | 
    
         
            +
                  },
         
     | 
| 
      
 54 
     | 
    
         
            +
                  :tables => { "Claim" => ["ClaimID", %w{Incident DateTime}]}
         
     | 
| 
      
 55 
     | 
    
         
            +
                },
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                { :should => "absorb an objectified binary with single-role UC",
         
     | 
| 
      
 58 
     | 
    
         
            +
                  :cql => %Q{
         
     | 
| 
      
 59 
     | 
    
         
            +
                    #{Prologue} #{Claim} #{Party} #{Person}
         
     | 
| 
      
 60 
     | 
    
         
            +
                    Lodgement is where
         
     | 
| 
      
 61 
     | 
    
         
            +
                      Claim was lodged by at most one Person;
         
     | 
| 
      
 62 
     | 
    
         
            +
                    Lodgement was made at at most one DateTime;
         
     | 
| 
      
 63 
     | 
    
         
            +
                    Person has exactly one birth-Date;
         
     | 
| 
      
 64 
     | 
    
         
            +
                  },
         
     | 
| 
      
 65 
     | 
    
         
            +
                  :tables => {
         
     | 
| 
      
 66 
     | 
    
         
            +
                    "Claim" => ["ClaimID", %w{Lodgement DateTime}, %w{Lodgement Person ID}],
         
     | 
| 
      
 67 
     | 
    
         
            +
                    "Party" => ["PartyID", %w{Person birth Date}]
         
     | 
| 
      
 68 
     | 
    
         
            +
                  }
         
     | 
| 
      
 69 
     | 
    
         
            +
                },
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              ]
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              setup do
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              Tests.each do |test|
         
     | 
| 
      
 77 
     | 
    
         
            +
                should = test[:should]
         
     | 
| 
      
 78 
     | 
    
         
            +
                cql = test[:cql]
         
     | 
| 
      
 79 
     | 
    
         
            +
                expected_tables = test[:tables]
         
     | 
| 
      
 80 
     | 
    
         
            +
                it "should #{should}" do
         
     | 
| 
      
 81 
     | 
    
         
            +
                  @compiler = ActiveFacts::Input::CQL.new(cql, should)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @vocabulary = @compiler.read
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  # Ensure that the same tables were generated:
         
     | 
| 
      
 85 
     | 
    
         
            +
                  tables = @vocabulary.tables
         
     | 
| 
      
 86 
     | 
    
         
            +
                  tables.map(&:name).sort.should == expected_tables.keys.sort
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  # Ensure that the same column descriptions were generated:
         
     | 
| 
      
 89 
     | 
    
         
            +
                  tables.sort_by(&:name).each do |table|
         
     | 
| 
      
 90 
     | 
    
         
            +
                    column_descriptions = table.absorbed_roles.all_role_ref.map{|rr| rr.column_name(nil) }.sort
         
     | 
| 
      
 91 
     | 
    
         
            +
                    column_descriptions.should == expected_tables[table.name].map{|c| Array(c) }.sort
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
              end
         
     | 
| 
      
 95 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # ActiveFacts tests: Value instances in the Runtime API
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            describe "AutoCounter Value Type instances" do
         
     | 
| 
      
 6 
     | 
    
         
            +
              setup do
         
     | 
| 
      
 7 
     | 
    
         
            +
                Object.send :remove_const, :Mod if Object.const_defined?("Mod")
         
     | 
| 
      
 8 
     | 
    
         
            +
                module Mod
         
     | 
| 
      
 9 
     | 
    
         
            +
                  class ThingId < AutoCounter
         
     | 
| 
      
 10 
     | 
    
         
            +
                    value_type
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  class Thing
         
     | 
| 
      
 13 
     | 
    
         
            +
                    identified_by :thing_id
         
     | 
| 
      
 14 
     | 
    
         
            +
                    has_one :thing_id
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  class Ordinal < Int
         
     | 
| 
      
 17 
     | 
    
         
            +
                    value_type
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  class ThingFacet
         
     | 
| 
      
 20 
     | 
    
         
            +
                    identified_by :thing, :ordinal
         
     | 
| 
      
 21 
     | 
    
         
            +
                    has_one :thing
         
     | 
| 
      
 22 
     | 
    
         
            +
                    has_one :ordinal
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
                @constellation = ActiveFacts::API::Constellation.new(Mod)
         
     | 
| 
      
 26 
     | 
    
         
            +
                @thing = Mod::Thing.new(:new)
         
     | 
| 
      
 27 
     | 
    
         
            +
                @thing_id = Mod::ThingId.new
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              it "should respond to verbalise" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                @thing_id.respond_to?(:verbalise).should be_true
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              it "should verbalise correctly" do
         
     | 
| 
      
 35 
     | 
    
         
            +
                @thing_id.verbalise.should =~ /ThingId 'new_[0-9]+'/
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              it "should respond to constellation" do
         
     | 
| 
      
 39 
     | 
    
         
            +
                @thing_id.respond_to?(:constellation).should be_true
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              it "should respond to its roles" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                @thing_id.respond_to?(:all_thing).should be_true
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              it "should allow prevent invalid role assignment" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                lambda {
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @thing.thing_id = "foo"
         
     | 
| 
      
 49 
     | 
    
         
            +
                  }.should raise_error
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              it "should allow its roles to be assigned" do
         
     | 
| 
      
 53 
     | 
    
         
            +
                lambda {
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @thing.thing_id = @thing_id
         
     | 
| 
      
 55 
     | 
    
         
            +
                  }.should_not raise_error
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              it "should allow an existing counter to be re-used" do
         
     | 
| 
      
 59 
     | 
    
         
            +
                @new_thing = Mod::Thing.new(@thing_id)
         
     | 
| 
      
 60 
     | 
    
         
            +
                @new_thing.thing_id.should == @thing_id
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              it "should return the ValueType in response to .class()" do
         
     | 
| 
      
 64 
     | 
    
         
            +
                @thing_id.class.vocabulary.should == Mod
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              it "should not allow a counter to be cloned" do
         
     | 
| 
      
 68 
     | 
    
         
            +
                lambda {
         
     | 
| 
      
 69 
     | 
    
         
            +
                  @thing_id.clone
         
     | 
| 
      
 70 
     | 
    
         
            +
                }.should raise_error
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              it "should allow an existing counter-identified object to be re-used" do
         
     | 
| 
      
 74 
     | 
    
         
            +
                thing = @constellation.Thing(:new)
         
     | 
| 
      
 75 
     | 
    
         
            +
                facets = []
         
     | 
| 
      
 76 
     | 
    
         
            +
                facets << @constellation.ThingFacet(thing, 0)
         
     | 
| 
      
 77 
     | 
    
         
            +
                facets << @constellation.ThingFacet(thing, 1)
         
     | 
| 
      
 78 
     | 
    
         
            +
                facets[0].thing.object_id.should == facets[1].thing.object_id
         
     | 
| 
      
 79 
     | 
    
         
            +
                facets[0].thing.thing_id.object_id.should == facets[1].thing.thing_id.object_id
         
     | 
| 
      
 80 
     | 
    
         
            +
              end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,130 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # ActiveFacts tests: Constellation instances in the Runtime API
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "ruby-debug"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            require 'activefacts/api'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            describe "A Constellation instance" do
         
     | 
| 
      
 10 
     | 
    
         
            +
              setup do
         
     | 
| 
      
 11 
     | 
    
         
            +
                Object.send :remove_const, :Mod if Object.const_defined?("Mod")
         
     | 
| 
      
 12 
     | 
    
         
            +
                module Mod
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @base_types = [
         
     | 
| 
      
 14 
     | 
    
         
            +
                      Int, Real, AutoCounter, String, Date, DateTime
         
     | 
| 
      
 15 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  # Create a value type and a subtype of that value type for each base type:
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @base_types.each do |base_type|
         
     | 
| 
      
 19 
     | 
    
         
            +
                    eval %Q{
         
     | 
| 
      
 20 
     | 
    
         
            +
                      class #{base_type.name}Value < #{base_type.name}
         
     | 
| 
      
 21 
     | 
    
         
            +
                        value_type
         
     | 
| 
      
 22 
     | 
    
         
            +
                      end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                      class #{base_type.name}SubValue < #{base_type.name}Value
         
     | 
| 
      
 25 
     | 
    
         
            +
                        # Note no new "value_type" is required here, it comes through inheritance
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  class Name < StringValue
         
     | 
| 
      
 31 
     | 
    
         
            +
                    value_type
         
     | 
| 
      
 32 
     | 
    
         
            +
                    #has_one :attr, Name
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  class LegalEntity
         
     | 
| 
      
 36 
     | 
    
         
            +
                    identified_by :name
         
     | 
| 
      
 37 
     | 
    
         
            +
                    has_one :name
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  class SurrogateId
         
     | 
| 
      
 41 
     | 
    
         
            +
                    identified_by :auto_counter_value
         
     | 
| 
      
 42 
     | 
    
         
            +
                    has_one :auto_counter_value
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  class Company < LegalEntity
         
     | 
| 
      
 46 
     | 
    
         
            +
                    supertypes SurrogateId
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  class Person < LegalEntity
         
     | 
| 
      
 50 
     | 
    
         
            +
                    identified_by :name, :family_name     # REVISIT: want a way to role_alias :name, :given_name
         
     | 
| 
      
 51 
     | 
    
         
            +
                    supertypes SurrogateId
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    has_one :family_name, :Name
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
                @constellation = ActiveFacts::API::Constellation.new(Mod)
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              it "should support fetching its vocabulary" do
         
     | 
| 
      
 60 
     | 
    
         
            +
                @constellation.vocabulary.should == Mod
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            #  it "should support fetching its query" do
         
     | 
| 
      
 64 
     | 
    
         
            +
            #    pending
         
     | 
| 
      
 65 
     | 
    
         
            +
            #    @constellation.query.should == Mod
         
     | 
| 
      
 66 
     | 
    
         
            +
            #  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              it "should support methods to construct instances of any concept" do
         
     | 
| 
      
 69 
     | 
    
         
            +
                name = foo = acme = fred_fly = nil
         
     | 
| 
      
 70 
     | 
    
         
            +
                lambda {
         
     | 
| 
      
 71 
     | 
    
         
            +
                    name = @constellation.Name("foo")
         
     | 
| 
      
 72 
     | 
    
         
            +
                    foo = @constellation.LegalEntity("foo")
         
     | 
| 
      
 73 
     | 
    
         
            +
                    acme = @constellation.Company("Acme, Inc")
         
     | 
| 
      
 74 
     | 
    
         
            +
                    fred_fly = @constellation.Person("fred", "fly")
         
     | 
| 
      
 75 
     | 
    
         
            +
                  }.should_not raise_error
         
     | 
| 
      
 76 
     | 
    
         
            +
                name.class.should == Mod::Name
         
     | 
| 
      
 77 
     | 
    
         
            +
                name.constellation.should == @constellation
         
     | 
| 
      
 78 
     | 
    
         
            +
                foo.class.should == Mod::LegalEntity
         
     | 
| 
      
 79 
     | 
    
         
            +
                foo.constellation.should == @constellation
         
     | 
| 
      
 80 
     | 
    
         
            +
                acme.class.should == Mod::Company
         
     | 
| 
      
 81 
     | 
    
         
            +
                acme.constellation.should == @constellation
         
     | 
| 
      
 82 
     | 
    
         
            +
                fred_fly.class.should == Mod::Person
         
     | 
| 
      
 83 
     | 
    
         
            +
                fred_fly.constellation.should == @constellation
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              it "should re-use instances constructed the same way" do
         
     | 
| 
      
 87 
     | 
    
         
            +
                name1 = @constellation.Name("foo")
         
     | 
| 
      
 88 
     | 
    
         
            +
                foo1 = @constellation.LegalEntity("foo")
         
     | 
| 
      
 89 
     | 
    
         
            +
                acme1 = @constellation.Company("Acme, Inc")
         
     | 
| 
      
 90 
     | 
    
         
            +
                fred_fly1 = @constellation.Person("fred", "fly")
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                name2 = @constellation.Name("foo")
         
     | 
| 
      
 93 
     | 
    
         
            +
                foo2 = @constellation.LegalEntity("foo")
         
     | 
| 
      
 94 
     | 
    
         
            +
                acme2 = @constellation.Company("Acme, Inc")
         
     | 
| 
      
 95 
     | 
    
         
            +
                fred_fly2 = @constellation.Person("fred", "fly")
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                name1.object_id.should == name2.object_id
         
     | 
| 
      
 98 
     | 
    
         
            +
                foo1.object_id.should == foo2.object_id
         
     | 
| 
      
 99 
     | 
    
         
            +
                acme1.object_id.should == acme2.object_id
         
     | 
| 
      
 100 
     | 
    
         
            +
                fred_fly1.object_id.should == fred_fly2.object_id
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              it "should index value instances, including by its superclasses" do
         
     | 
| 
      
 104 
     | 
    
         
            +
                baz = @constellation.Name("baz")
         
     | 
| 
      
 105 
     | 
    
         
            +
                @constellation.Name.keys.sort.should == ["baz"]
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                @constellation.StringValue.keys.sort.should == ["baz"]
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
              it "should index entity instances, including by its superclass and secondary supertypes" do
         
     | 
| 
      
 111 
     | 
    
         
            +
                name = "Acme, Inc"
         
     | 
| 
      
 112 
     | 
    
         
            +
                fred = "Fred"
         
     | 
| 
      
 113 
     | 
    
         
            +
                fly = "Fly"
         
     | 
| 
      
 114 
     | 
    
         
            +
                acme = @constellation.Company name, :auto_counter_value => :new
         
     | 
| 
      
 115 
     | 
    
         
            +
                fred_fly = @constellation.Person fred, fly, :auto_counter_value => :new
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                # REVISIT: This should be illegal:
         
     | 
| 
      
 118 
     | 
    
         
            +
                #fred_fly.auto_counter_value = :new
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                @constellation.Person.keys.sort.should == [[fred, fly]]
         
     | 
| 
      
 121 
     | 
    
         
            +
                @constellation.Company.keys.sort.should == [[name]]
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                @constellation.LegalEntity.keys.sort.should be_include([name])
         
     | 
| 
      
 124 
     | 
    
         
            +
                @constellation.LegalEntity.keys.sort.should be_include([fred])
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                @constellation.SurrogateId.values.should be_include(acme)
         
     | 
| 
      
 127 
     | 
    
         
            +
                @constellation.SurrogateId.values.should be_include(fred_fly)
         
     | 
| 
      
 128 
     | 
    
         
            +
              end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,101 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # ActiveFacts tests: Entity classes in the Runtime API
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            describe "Entity Type class definitions" do
         
     | 
| 
      
 6 
     | 
    
         
            +
              setup do
         
     | 
| 
      
 7 
     | 
    
         
            +
                Object.send :remove_const, :Mod if Object.const_defined?("Mod")
         
     | 
| 
      
 8 
     | 
    
         
            +
                module Mod
         
     | 
| 
      
 9 
     | 
    
         
            +
                  class Name < String
         
     | 
| 
      
 10 
     | 
    
         
            +
                    value_type
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  class LegalEntity
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  class Person < LegalEntity
         
     | 
| 
      
 15 
     | 
    
         
            +
                    identified_by :name
         
     | 
| 
      
 16 
     | 
    
         
            +
                    has_one :name, Name
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              it "should respond_to verbalise" do
         
     | 
| 
      
 22 
     | 
    
         
            +
                Mod::Person.respond_to?(:verbalise).should be_true
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              it "should not pollute the superclass" do
         
     | 
| 
      
 26 
     | 
    
         
            +
                Mod::LegalEntity.respond_to?(:verbalise).should_not be_true
         
     | 
| 
      
 27 
     | 
    
         
            +
                Class.respond_to?(:verbalise).should_not be_true
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              it "should return a string from verbalise" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                v = Mod::Person.verbalise
         
     | 
| 
      
 32 
     | 
    
         
            +
                v.should_not be_nil
         
     | 
| 
      
 33 
     | 
    
         
            +
                v.should_not =~ /REVISIT/
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              it "should respond_to vocabulary" do
         
     | 
| 
      
 37 
     | 
    
         
            +
                Mod::Person.respond_to?(:vocabulary).should be_true
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              it "should return the parent module as the vocabulary" do
         
     | 
| 
      
 41 
     | 
    
         
            +
                vocabulary = Mod::Person.vocabulary
         
     | 
| 
      
 42 
     | 
    
         
            +
                vocabulary.should == Mod
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              it "should return a vocabulary that knows about this concept" do
         
     | 
| 
      
 46 
     | 
    
         
            +
                vocabulary = Mod::Person.vocabulary
         
     | 
| 
      
 47 
     | 
    
         
            +
                vocabulary.respond_to?(:concept).should be_true
         
     | 
| 
      
 48 
     | 
    
         
            +
                vocabulary.concept.has_key?("Person").should be_true
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
              it "should respond to roles()" do
         
     | 
| 
      
 52 
     | 
    
         
            +
                Mod::Person.respond_to?(:roles).should be_true
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              it "should contain only the added role definition" do
         
     | 
| 
      
 56 
     | 
    
         
            +
                Mod::Person.roles.size.should == 1
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              it "should return the role definition" do
         
     | 
| 
      
 60 
     | 
    
         
            +
                # Check the role definition may be accessed by passing an index:
         
     | 
| 
      
 61 
     | 
    
         
            +
                Mod::Person.roles(0).should be_nil
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                role = Mod::Person.roles(:name)
         
     | 
| 
      
 64 
     | 
    
         
            +
                role.should_not be_nil
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                role = Mod::Person.roles("name")
         
     | 
| 
      
 67 
     | 
    
         
            +
                role.should_not be_nil
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                # Check the role definition may be accessed by indexing the returned hash:
         
     | 
| 
      
 70 
     | 
    
         
            +
                role = Mod::Person.roles[:name]
         
     | 
| 
      
 71 
     | 
    
         
            +
                role.should_not be_nil
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                # Check the role definition array by .include?
         
     | 
| 
      
 74 
     | 
    
         
            +
                Mod::Person.roles.include?(:name).should be_true
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              it "should fail on a ValueClass" do
         
     | 
| 
      
 78 
     | 
    
         
            +
                lambda{
         
     | 
| 
      
 79 
     | 
    
         
            +
                  class SomeClass < String
         
     | 
| 
      
 80 
     | 
    
         
            +
                    identified_by
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
                }.should raise_error
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
              it "should return the identifying roles" do
         
     | 
| 
      
 86 
     | 
    
         
            +
                Mod::Person.identifying_roles.should == [:name]
         
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
              it "should prevent a role name from matching a concept that exists unless that concept is the player" do
         
     | 
| 
      
 90 
     | 
    
         
            +
                lambda {
         
     | 
| 
      
 91 
     | 
    
         
            +
                    module Mod
         
     | 
| 
      
 92 
     | 
    
         
            +
                      class LegalEntity
         
     | 
| 
      
 93 
     | 
    
         
            +
                      end
         
     | 
| 
      
 94 
     | 
    
         
            +
                      class Bad
         
     | 
| 
      
 95 
     | 
    
         
            +
                        identified_by :name
         
     | 
| 
      
 96 
     | 
    
         
            +
                        has_one :name, LegalEntity
         
     | 
| 
      
 97 
     | 
    
         
            +
                      end
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
                  }.should raise_error
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
            end
         
     |