activefacts 0.8.9 → 0.8.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/.gemtest +0 -0
  2. data/Manifest.txt +28 -33
  3. data/Rakefile +11 -12
  4. data/bin/cql +90 -46
  5. data/examples/CQL/Blog.cql +2 -1
  6. data/examples/CQL/CompanyDirectorEmployee.cql +2 -2
  7. data/examples/CQL/Death.cql +1 -1
  8. data/examples/CQL/Diplomacy.cql +9 -9
  9. data/examples/CQL/Genealogy.cql +3 -2
  10. data/examples/CQL/Insurance.cql +10 -7
  11. data/examples/CQL/JoinEquality.cql +2 -2
  12. data/examples/CQL/Marriage.cql +1 -1
  13. data/examples/CQL/Metamodel.cql +73 -53
  14. data/examples/CQL/MetamodelNext.cql +89 -67
  15. data/examples/CQL/OneToOnes.cql +2 -2
  16. data/examples/CQL/ServiceDirector.cql +10 -5
  17. data/examples/CQL/Supervision.cql +3 -3
  18. data/examples/CQL/Tests.Test5.Load.cql +1 -1
  19. data/examples/CQL/Warehousing.cql +4 -2
  20. data/lib/activefacts/cql/CQLParser.treetop +26 -60
  21. data/lib/activefacts/cql/Context.treetop +12 -2
  22. data/lib/activefacts/cql/Expressions.treetop +14 -30
  23. data/lib/activefacts/cql/FactTypes.treetop +165 -110
  24. data/lib/activefacts/cql/Language/English.treetop +167 -54
  25. data/lib/activefacts/cql/LexicalRules.treetop +16 -2
  26. data/lib/activefacts/cql/{Concepts.treetop → ObjectTypes.treetop} +36 -37
  27. data/lib/activefacts/cql/Terms.treetop +57 -27
  28. data/lib/activefacts/cql/ValueTypes.treetop +39 -13
  29. data/lib/activefacts/cql/compiler.rb +5 -3
  30. data/lib/activefacts/cql/compiler/{reading.rb → clause.rb} +407 -285
  31. data/lib/activefacts/cql/compiler/constraint.rb +178 -275
  32. data/lib/activefacts/cql/compiler/entity_type.rb +73 -64
  33. data/lib/activefacts/cql/compiler/expression.rb +418 -0
  34. data/lib/activefacts/cql/compiler/fact.rb +146 -145
  35. data/lib/activefacts/cql/compiler/fact_type.rb +197 -80
  36. data/lib/activefacts/cql/compiler/join.rb +159 -0
  37. data/lib/activefacts/cql/compiler/shared.rb +51 -23
  38. data/lib/activefacts/cql/compiler/value_type.rb +56 -2
  39. data/lib/activefacts/cql/parser.rb +15 -4
  40. data/lib/activefacts/generate/absorption.rb +7 -7
  41. data/lib/activefacts/generate/cql.rb +100 -37
  42. data/lib/activefacts/generate/oo.rb +28 -51
  43. data/lib/activefacts/generate/ordered.rb +60 -36
  44. data/lib/activefacts/generate/ruby.rb +6 -6
  45. data/lib/activefacts/generate/sql/server.rb +4 -4
  46. data/lib/activefacts/input/orm.rb +71 -53
  47. data/lib/activefacts/persistence.rb +1 -1
  48. data/lib/activefacts/persistence/columns.rb +27 -23
  49. data/lib/activefacts/persistence/foreignkey.rb +6 -6
  50. data/lib/activefacts/persistence/index.rb +17 -17
  51. data/lib/activefacts/persistence/{concept.rb → object_type.rb} +9 -9
  52. data/lib/activefacts/persistence/reference.rb +61 -36
  53. data/lib/activefacts/persistence/tables.rb +61 -59
  54. data/lib/activefacts/support.rb +54 -29
  55. data/lib/activefacts/version.rb +1 -1
  56. data/lib/activefacts/vocabulary/extensions.rb +99 -54
  57. data/lib/activefacts/vocabulary/metamodel.rb +43 -37
  58. data/lib/activefacts/vocabulary/verbaliser.rb +134 -109
  59. data/spec/absorption_spec.rb +8 -8
  60. data/spec/cql/comparison_spec.rb +91 -0
  61. data/spec/cql/contractions_spec.rb +251 -0
  62. data/spec/cql/entity_type_spec.rb +319 -0
  63. data/spec/cql/expressions_spec.rb +63 -0
  64. data/spec/cql/fact_type_matching_spec.rb +283 -0
  65. data/spec/cql/french_spec.rb +21 -0
  66. data/spec/cql/parser/bad_literals_spec.rb +86 -0
  67. data/spec/cql/parser/constraints_spec.rb +19 -0
  68. data/spec/cql/parser/entity_types_spec.rb +106 -0
  69. data/spec/cql/parser/expressions_spec.rb +179 -0
  70. data/spec/cql/parser/fact_types_spec.rb +41 -0
  71. data/spec/cql/parser/literals_spec.rb +312 -0
  72. data/spec/cql/parser/pragmas_spec.rb +89 -0
  73. data/spec/cql/parser/value_types_spec.rb +42 -0
  74. data/spec/cql/role_matching_spec.rb +147 -0
  75. data/spec/cql/samples_spec.rb +9 -9
  76. data/spec/cql_cql_spec.rb +1 -1
  77. data/spec/cql_dm_spec.rb +116 -0
  78. data/spec/cql_mysql_spec.rb +1 -1
  79. data/spec/cql_ruby_spec.rb +1 -1
  80. data/spec/cql_sql_spec.rb +3 -3
  81. data/spec/cql_symbol_tables_spec.rb +30 -30
  82. data/spec/cqldump_spec.rb +4 -4
  83. data/spec/helpers/array_matcher.rb +32 -27
  84. data/spec/helpers/diff_matcher.rb +6 -26
  85. data/spec/helpers/file_matcher.rb +41 -32
  86. data/spec/helpers/parse_to_ast_matcher.rb +76 -0
  87. data/spec/helpers/string_matcher.rb +32 -31
  88. data/spec/norma_cql_spec.rb +1 -1
  89. data/spec/norma_ruby_spec.rb +1 -1
  90. data/spec/norma_ruby_sql_spec.rb +1 -1
  91. data/spec/norma_sql_spec.rb +3 -1
  92. data/spec/norma_tables_spec.rb +1 -1
  93. data/spec/ruby_api_spec.rb +23 -0
  94. data/spec/spec_helper.rb +5 -4
  95. metadata +66 -66
  96. data/examples/CQL/OrienteeringER.cql +0 -58
  97. data/lib/activefacts/api.rb +0 -44
  98. data/lib/activefacts/api/concept.rb +0 -410
  99. data/lib/activefacts/api/constellation.rb +0 -128
  100. data/lib/activefacts/api/entity.rb +0 -256
  101. data/lib/activefacts/api/instance.rb +0 -60
  102. data/lib/activefacts/api/instance_index.rb +0 -80
  103. data/lib/activefacts/api/numeric.rb +0 -167
  104. data/lib/activefacts/api/role.rb +0 -80
  105. data/lib/activefacts/api/role_proxy.rb +0 -70
  106. data/lib/activefacts/api/role_values.rb +0 -117
  107. data/lib/activefacts/api/standard_types.rb +0 -87
  108. data/lib/activefacts/api/support.rb +0 -65
  109. data/lib/activefacts/api/value.rb +0 -135
  110. data/lib/activefacts/api/vocabulary.rb +0 -82
  111. data/spec/api/autocounter.rb +0 -82
  112. data/spec/api/constellation.rb +0 -130
  113. data/spec/api/entity_type.rb +0 -103
  114. data/spec/api/instance.rb +0 -461
  115. data/spec/api/roles.rb +0 -124
  116. data/spec/api/value_type.rb +0 -112
  117. data/spec/api_spec.rb +0 -13
  118. data/spec/cql/matching_spec.rb +0 -517
  119. data/spec/cql/unit_spec.rb +0 -394
  120. data/spec/spec.opts +0 -1
@@ -1,128 +0,0 @@
1
- #
2
- # ActiveFacts Runtime API
3
- # Constellation class
4
- #
5
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
- #
7
-
8
- module ActiveFacts
9
- module API #:nodoc:
10
- # A Constellation is a population of instances of the Concept classes of a Vocabulary.
11
- # Every concept class is either a Value type or an Entity type.
12
- #
13
- # Value types are uniquely identified by their value, and a constellation will only
14
- # ever have a single instance of a given value of that class.
15
- #
16
- # Entity instances are uniquely identified by their identifying roles, and again, a
17
- # constellation will only ever have a single entity instance for the values of those
18
- # identifying roles.
19
- #
20
- # As a result, you cannot "create" an object in a constellation - you merely _assert_
21
- # its existence. This is done using method_missing; @constellation.Thing(3) creates
22
- # an instance (or returns the existing instance) of Thing identified by the value 3.
23
- # You can also use the populate() method to apply a block of assertions.
24
- #
25
- # You can instance##retract any instance, and that removes it from the constellation (will
26
- # delete it from the database when the constellation is saved), and nullifies any
27
- # references to it.
28
- #
29
- # A Constellation may or not be valid according to the vocabulary's constraints,
30
- # but it may also represent a portion of a larger population (a database) with
31
- # which it may be merged to form a valid population. In other words, an invalid
32
- # Constellation may be invalid only because it lacks some of the facts.
33
- #
34
- class Constellation
35
- attr_reader :vocabulary
36
- # All instances are indexed in this hash, keyed by the class object. Each instance is indexed for every supertype it has (including multiply-inherited ones). It's a bad idea to try to modify these indexes!
37
- attr_reader :instances # Can say c.instances[MyClass].each{|k, v| ... }
38
- # Can also say c.MyClass.each{|k, v| ... }
39
-
40
- # Create a new empty Constellation over the given Vocabulary
41
- def initialize(vocabulary)
42
- @vocabulary = vocabulary
43
- @instances = Hash.new do |h,k|
44
- raise "A constellation over #{@vocabulary.name} can only index instances of concepts in that vocabulary, not #{k.inspect}" unless k.is_a?(Class) and k.modspace == vocabulary
45
- h[k] = InstanceIndex.new
46
- end
47
- end
48
-
49
- def inspect #:nodoc:
50
- "Constellation:#{object_id}"
51
- end
52
-
53
- # Evaluate assertions against the population of this Constellation
54
- def populate *args, &block
55
- # REVISIT: Use args for something? Like options to enable/disable validation?
56
- instance_eval(&block)
57
- end
58
-
59
- # Delete instances from the constellation, nullifying (or cascading) the roles each plays
60
- def retract(*instances)
61
- Array(instances).each do |i|
62
- i.retract
63
- end
64
- end
65
-
66
- # Constellations verbalise all members of all classes in alphabetical order, showing
67
- # non-identifying role values as well
68
- def verbalise
69
- "Constellation over #{vocabulary.name}:\n" +
70
- vocabulary.concept.keys.sort.map{|concept|
71
- klass = vocabulary.const_get(concept)
72
-
73
- # REVISIT: It would be better not to rely on the role name pattern here:
74
- single_roles, multiple_roles = klass.roles.keys.sort_by(&:to_s).partition{|r| r.to_s !~ /\Aall_/ }
75
- single_roles -= klass.identifying_role_names if (klass.is_entity_type)
76
- # REVISIT: Need to include superclass roles also.
77
-
78
- instances = send(concept.to_sym)
79
- next nil unless instances.size > 0
80
- "\tEvery #{concept}:\n" +
81
- instances.map{|key, instance|
82
- s = "\t\t" + instance.verbalise
83
- if (single_roles.size > 0)
84
- role_values =
85
- single_roles.map{|role|
86
- [ role_name = role.to_s.camelcase(true),
87
- value = instance.send(role)]
88
- }.select{|role_name, value|
89
- value
90
- }.map{|role_name, value|
91
- "#{role_name} = #{value ? value.verbalise : "nil"}"
92
- }
93
- s += " where " + role_values*", " if role_values.size > 0
94
- end
95
- s
96
- } * "\n"
97
- }.compact*"\n"
98
- end
99
-
100
- # This method removes the given instance from this constellation's indexes
101
- # It must be called before the identifying roles get deleted or nullified.
102
- def __retract(instance) #:nodoc:
103
- # REVISIT: Need to search, as key values are gone already. Is there a faster way?
104
- ([instance.class]+instance.class.supertypes_transitive).each do |klass|
105
- @instances[klass].delete_if{|k,v| v == instance }
106
- end
107
- # REVISIT: Need to nullify all the roles this object plays.
108
- # If mandatory on the counterpart side, this may/must propagate the delete (without mutual recursion!)
109
- end
110
-
111
- # With parameters, assert an instance of the concept whose name is the missing method, identified by the values passed as *args*.
112
- # With no parameters, return the collection of all instances of that concept.
113
- def method_missing(m, *args)
114
- if klass = @vocabulary.const_get(m)
115
- if args.size == 0
116
- # Return the collection of all instances of this class in the constellation:
117
- @instances[klass]
118
- else
119
- # Assert a new ground fact (concept instance) of the specified class, identified by args:
120
- # REVISIT: create a constructor method here instead?
121
- instance, key = klass.assert_instance(self, args)
122
- instance
123
- end
124
- end
125
- end
126
- end
127
- end
128
- end
@@ -1,256 +0,0 @@
1
- #
2
- # ActiveFacts Runtime API
3
- # Entity class (a mixin module for the class Class)
4
- #
5
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
- #
7
- module ActiveFacts
8
- module API
9
- # An Entity type is any Concept that isn't a value type.
10
- # All Entity types must have an identifier made up of one or more roles.
11
- module Entity
12
- include Instance
13
-
14
- # Assign the identifying roles to initialise a new Entity instance.
15
- # The role values are asserted in the constellation first, so you
16
- # can pass bare values (array, string, integer, etc) for any role
17
- # whose instances can be constructed using those values.
18
- #
19
- # A value must be provided for every identifying role, but if the
20
- # last argument is a hash, they may come from there.
21
- #
22
- # Any additional (non-identifying) roles may also be passed in the final hash.
23
- def initialize(*args)
24
- super(args)
25
- klass = self.class
26
- hash = {}
27
- hash = args.pop.clone if Hash === args[-1]
28
-
29
- # Pick any missing identifying roles out of the hash if possible:
30
- while args.size < (ir = klass.identifying_role_names).size
31
- value = hash[role = ir[args.size]]
32
- hash.delete(role)
33
- args.push value
34
- end
35
-
36
- # If one arg is expected but more are passed, they might be the args for the object that plays the identifying role:
37
- args = [args] if klass.identifying_role_names.size == 1 && args.size > 1
38
-
39
- # This should now only occur when there are too many args passed:
40
- raise "Wrong number of parameters to #{klass}.new, " +
41
- "expect (#{klass.identifying_role_names*","}) " +
42
- "got (#{args.map{|a| a.to_s.inspect}*", "})" if args.size != klass.identifying_role_names.size
43
-
44
- # Assign the identifying roles in order, then the other roles passed as a hash:
45
- (klass.identifying_role_names.zip(args) + hash.entries).each do |role_name, value|
46
- role = klass.roles(role_name)
47
- send("#{role_name}=", value)
48
- end
49
- end
50
-
51
- def inspect #:nodoc:
52
- "\#<#{
53
- self.class.basename
54
- }:#{
55
- object_id
56
- }#{
57
- constellation ? " in #{constellation.inspect}" : ""
58
- } #{
59
- # REVISIT: Where there are one-to-one roles, this cycles
60
- self.class.identifying_role_names.map{|role| "@#{role}="+send(role).inspect }*" "
61
- }>"
62
- end
63
-
64
- # When used as a hash key, the hash key of this entity instance is calculated
65
- # by hashing the values of its identifying roles
66
- def hash
67
- self.class.identifying_role_names.map{|role|
68
- instance_variable_get("@#{role}")
69
- }.inject(0) { |h,v|
70
- h ^= v.hash
71
- h
72
- }
73
- end
74
-
75
- # When used as a hash key, this entity instance is compared with another by
76
- # comparing the values of its identifying roles
77
- def eql?(other)
78
- return false unless self.class == other.class
79
- self.class.identifying_role_names.each{|role|
80
- return false unless send(role).eql?(other.send(role))
81
- }
82
- return true
83
- end
84
-
85
- # Verbalise this entity instance
86
- def verbalise(role_name = nil)
87
- "#{role_name || self.class.basename}(#{
88
- self.class.identifying_role_names.map{|role_sym|
89
- value = send(role_sym)
90
- role_name = self.class.roles(role_sym).name.to_s.camelcase(true)
91
- value ? value.verbalise(role_name) : "nil"
92
- }*", "
93
- })"
94
- end
95
-
96
- # Return the array of the values of this entity instance's identifying roles
97
- def identifying_role_values
98
- self.class.identifying_role_names.map{|role|
99
- send(role)
100
- }
101
- end
102
-
103
- # All classes that become Entity types receive the methods of this class as class methods:
104
- module ClassMethods
105
- include Instance::ClassMethods
106
-
107
- # Return the array of Role objects that define the identifying relationships of this Entity type:
108
- def identifying_role_names
109
- @identifying_role_names ||= []
110
- end
111
-
112
- def identifying_roles
113
- debug :persistence, "Identifying roles for #{basename}" do
114
- @identifying_role_names.map{|name|
115
- role = roles[name] || (!superclass.is_entity_type || superclass.roles[name])
116
- debug :persistence, "#{name} -> #{role ? "found" : "NOT FOUND"}"
117
- role
118
- }
119
- end
120
- end
121
-
122
- # Convert the passed arguments into an array of Instance objects that can identify an instance of this Entity type:
123
- def identifying_role_values(*args)
124
- #puts "Getting identifying role values #{identifying_role_names.inspect} of #{basename} using #{args.inspect}"
125
-
126
- # If the single arg is an instance of the correct class or a subclass,
127
- # use the instance's identifying_role_values
128
- if (args.size == 1 and
129
- (arg = args[0]).is_a?(self)) # REVISIT: or a secondary supertype
130
- arg = arg.__getobj__ if RoleProxy === arg
131
- return arg.identifying_role_values
132
- end
133
-
134
- ir = identifying_role_names
135
- args, arg_hash = ActiveFacts::extract_hash_args(ir, args)
136
- if args.size < ir.size
137
- raise "#{basename} requires all identifying values, you're missing #{ir[args.size..-1].map(&:to_sym)*', '}"
138
- elsif args.size > ir.size
139
- raise "#{basename} requires all identifying values, you have #{args.size-ir.size} extras #{args[ir.size..-1].map(&:inspect)*', '}"
140
- end
141
-
142
- role_args = ir.map{|role_sym| roles(role_sym)}.zip(args)
143
- role_args.map do |role, arg|
144
- #puts "Getting identifying_role_value for #{role.counterpart_concept.basename} using #{arg.inspect}"
145
- next nil unless arg
146
- next !!arg unless role.counterpart # Unary
147
- arg = arg.__getobj__ if RoleProxy === arg
148
- if arg.is_a?(role.counterpart_concept) # REVISIT: or a secondary supertype
149
- # Note that with a secondary supertype, it must still return the values of these identifying_role_names
150
- next arg.identifying_role_values
151
- end
152
- role.counterpart_concept.identifying_role_values(*arg)
153
- end
154
- end
155
-
156
- def assert_instance(constellation, args) #:nodoc:
157
- # Build the key for this instance from the args
158
- # The key of an instance is the value or array of keys of the identifying values.
159
- # The key values aren't necessarily present in the constellation, even after this.
160
- key = identifying_role_values(*args)
161
-
162
- # Find and return an existing instance matching this key
163
- instances = constellation.instances[self] # All instances of this class in this constellation
164
- instance = instances[key]
165
- # DEBUG: puts "assert #{self.basename} #{key.inspect} #{instance ? "exists" : "new"}"
166
- return instance, key if instance # A matching instance of this class
167
-
168
- # Now construct each of this object's identifying roles
169
- ir = identifying_role_names
170
- args, arg_hash = ActiveFacts::extract_hash_args(ir, args)
171
- role_values = ir.map{|role_sym| roles(role_sym)}.zip(args)
172
- key = [] # Gather the actual key (AutoCounters are special)
173
- values = role_values.map do |role, arg|
174
- if !arg
175
- value = role_key = nil # No value
176
- elsif !role.counterpart
177
- value = role_key = !!arg # Unary
178
- elsif arg.is_a?(role.counterpart_concept) # REVISIT: or a secondary supertype
179
- arg = arg.__getobj__ if RoleProxy === arg
180
- raise "Connecting values across constellations" unless arg.constellation == constellation
181
- value, role_key = arg, arg.identifying_role_values
182
- else
183
- value, role_key = role.counterpart_concept.assert_instance(constellation, Array(arg))
184
- end
185
- key << role_key
186
- value
187
- end
188
- values << arg_hash if arg_hash and !arg_hash.empty?
189
-
190
- #puts "Creating new #{basename} using #{values.inspect}"
191
- instance = new(*values)
192
-
193
- # Make the new entity instance a member of this constellation:
194
- instance.constellation = constellation
195
- return *index_instance(instance, key, ir)
196
- end
197
-
198
- def index_instance(instance, key = nil, key_roles = nil) #:nodoc:
199
- # Derive a new key if we didn't receive one or if the roles are different:
200
- unless key && key_roles && key_roles == identifying_role_names
201
- key = (key_roles = identifying_role_names).map do |role_name|
202
- instance.send role_name
203
- end
204
- end
205
-
206
- # Index the instance for this class in the constellation
207
- instances = instance.constellation.instances[self]
208
- instances[key] = instance
209
- # DEBUG: puts "indexing entity #{basename} using #{key.inspect} in #{constellation.object_id}"
210
-
211
- # Index the instance for each supertype:
212
- supertypes.each do |supertype|
213
- supertype.index_instance(instance, key, key_roles)
214
- end
215
-
216
- return instance, key
217
- end
218
-
219
- # A concept that isn't a ValueType must have an identification scheme,
220
- # which is a list of roles it plays. The identification scheme may be
221
- # inherited from a superclass.
222
- def initialise_entity_type(*args) #:nodoc:
223
- #puts "Initialising entity type #{self} using #{args.inspect}"
224
- @identifying_role_names = superclass.identifying_role_names if superclass.is_entity_type
225
- # REVISIT: @identifying_role_names here are the symbols passed in, not the Role objects we should use.
226
- # We'd need late binding to use Role objects...
227
- @identifying_role_names = args if args.size > 0 || !@identifying_role_names
228
- end
229
-
230
- def inherited(other) #:nodoc:
231
- other.identified_by *identifying_role_names
232
- subtypes << other unless subtypes.include? other
233
- #puts "#{self.name} inherited by #{other.name}"
234
- vocabulary.__add_concept(other)
235
- end
236
-
237
- # verbalise this concept
238
- def verbalise
239
- "#{basename} is identified by #{identifying_role_names.map{|role_sym| role_sym.to_s.camelcase(true)}*" and "};"
240
- end
241
- end
242
-
243
- def Entity.included other #:nodoc:
244
- other.send :extend, ClassMethods
245
-
246
- # Register ourselves with the parent module, which has become a Vocabulary:
247
- vocabulary = other.modspace
248
- # puts "Entity.included(#{other.inspect})"
249
- unless vocabulary.respond_to? :concept # Extend module with Vocabulary if necessary
250
- vocabulary.send :extend, Vocabulary
251
- end
252
- vocabulary.__add_concept(other)
253
- end
254
- end
255
- end
256
- end
@@ -1,60 +0,0 @@
1
- #
2
- # ActiveFacts Runtime API
3
- # Instance (mixin module for instances of a Concept - a class with Concept mixed in)
4
- #
5
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
- #
7
- # Instance methods are extended into all instances, whether of value or entity types.
8
- #
9
- module ActiveFacts
10
- module API
11
- # Every Instance of a Concept (A Value type or an Entity type) includes the methods of this module:
12
- module Instance
13
- # What constellation does this Instance belong to (if any):
14
- attr_accessor :constellation
15
-
16
- def initialize(args = []) #:nodoc:
17
- unless (self.class.is_entity_type)
18
- #if (self.class.superclass != Object)
19
- # puts "constructing #{self.class.superclass} with #{args.inspect}"
20
- super(*args)
21
- end
22
- end
23
-
24
- # Verbalise this instance
25
- def verbalise
26
- # This method should always be overridden in subclasses
27
- raise "#{self.class} Instance verbalisation needed"
28
- end
29
-
30
- # De-assign all functional roles and remove from constellation, if any.
31
- def retract
32
- # Delete from the constellation first, so it can remember our identifying role values
33
- @constellation.__retract(self) if @constellation
34
-
35
- # Now, for all roles (from this class and all supertypes), assign nil to all functional roles
36
- # The counterpart roles get cleared automatically.
37
- ([self.class]+self.class.supertypes_transitive).each do |klass|
38
- klass.roles.each do |role_name, role|
39
- next if role.unary?
40
- next if !role.unique
41
-
42
- counterpart = role.counterpart
43
- puts "Nullifying mandatory role #{role.name} of #{role.owner.name}" if counterpart.mandatory
44
-
45
- send "#{role.name}=", nil
46
- end
47
- end
48
- end
49
-
50
- module ClassMethods #:nodoc:
51
- include Concept
52
- # Add Instance class methods here
53
- end
54
-
55
- def Instance.included other #:nodoc:
56
- other.send :extend, ClassMethods
57
- end
58
- end
59
- end
60
- end
@@ -1,80 +0,0 @@
1
- #
2
- # ActiveFacts Runtime API
3
- # InstanceIndex class
4
- #
5
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
- #
7
- module ActiveFacts
8
- module API
9
- #
10
- # Each Constellation maintains an InstanceIndex for each Concept in its Vocabulary.
11
- # The InstanceIndex object is returned when you call @constellation.Concept with no
12
- # arguments (where Concept is the concept name you're interested in)
13
- #
14
- class InstanceIndex
15
- def []=(key, value) #:nodoc:
16
- raise "Adding RoleProxy to InstanceIndex" if value && RoleProxy === value
17
- h[key] = value
18
- end
19
-
20
- def [](*args)
21
- a = args
22
- #a = naked(args)
23
- # p "vvvv",
24
- # args,
25
- # a,
26
- # keys.map{|k| v=super(k); (RoleProxy === k ? "*" : "")+k.to_s+"=>"+(RoleProxy === v ? "*" : "")+v.to_s}*",",
27
- # "^^^^"
28
- h[*a]
29
- #super(*a)
30
- end
31
-
32
- def size
33
- h.size
34
- end
35
-
36
- def each &b
37
- h.each &b
38
- end
39
-
40
- def map &b
41
- h.map &b
42
- end
43
-
44
- def detect &b
45
- r = h.detect &b
46
- r ? r[1] : nil
47
- end
48
-
49
- # Return an array of all the instances of this concept
50
- def values
51
- h.values
52
- end
53
-
54
- # Return an array of the identifying role values arrays for all the instances of this concept
55
- def keys
56
- h.keys
57
- end
58
-
59
- def delete_if(&b) #:nodoc:
60
- h.delete_if &b
61
- end
62
-
63
- private
64
- def h
65
- @hash ||= {}
66
- end
67
-
68
- def naked(o)
69
- case o
70
- when Array
71
- o.map{|e| naked(e) }
72
- when RoleProxy
73
- o.__getobj__
74
- else
75
- o
76
- end
77
- end
78
- end
79
- end
80
- end