sdl-ng 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.yard_redcarpet_ext +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +454 -0
- data/Rakefile +16 -0
- data/bin/process_service_descriptions +102 -0
- data/examples/services/google_drive_for_business.service.rb +50 -0
- data/examples/services/salesforce_sales_cloud.service.rb +51 -0
- data/examples/translations/en.yml +184 -0
- data/examples/vocabulary/base/base.sdl.rb +8 -0
- data/examples/vocabulary/base/location.sdl.rb +5 -0
- data/examples/vocabulary/crf/characteristics.sdl.rb +25 -0
- data/examples/vocabulary/crf/charging.sdl.rb +8 -0
- data/examples/vocabulary/crf/compliance.sdl.rb +35 -0
- data/examples/vocabulary/crf/delivery.sdl.rb +22 -0
- data/examples/vocabulary/crf/dynamics.sdl.rb +6 -0
- data/examples/vocabulary/crf/interop.sdl.rb +54 -0
- data/examples/vocabulary/crf/optimizing.sdl.rb +15 -0
- data/examples/vocabulary/crf/portability.sdl.rb +25 -0
- data/examples/vocabulary/crf/protection.sdl.rb +8 -0
- data/examples/vocabulary/crf/reliability.sdl.rb +1 -0
- data/examples/vocabulary/crf/reputation.sdl.rb +3 -0
- data/lib/sdl.rb +17 -0
- data/lib/sdl/base.rb +20 -0
- data/lib/sdl/base/fact.rb +11 -0
- data/lib/sdl/base/property.rb +34 -0
- data/lib/sdl/base/service.rb +13 -0
- data/lib/sdl/base/service_compendium.rb +130 -0
- data/lib/sdl/base/type.rb +66 -0
- data/lib/sdl/exporters.rb +9 -0
- data/lib/sdl/exporters/exporter.rb +19 -0
- data/lib/sdl/exporters/markdown_service_exporter.rb +5 -0
- data/lib/sdl/exporters/rdf_exporter.rb +34 -0
- data/lib/sdl/exporters/rdf_mapping.rb +48 -0
- data/lib/sdl/exporters/schema_exporter.rb +9 -0
- data/lib/sdl/exporters/service_exporter.rb +9 -0
- data/lib/sdl/exporters/xml_mapping.rb +51 -0
- data/lib/sdl/exporters/xml_service_exporter.rb +37 -0
- data/lib/sdl/exporters/xsd_schema_exporter.rb +94 -0
- data/lib/sdl/receivers.rb +22 -0
- data/lib/sdl/receivers/fact_receiver.rb +15 -0
- data/lib/sdl/receivers/service_receiver.rb +63 -0
- data/lib/sdl/receivers/type_instance_receiver.rb +86 -0
- data/lib/sdl/receivers/type_receiver.rb +87 -0
- data/lib/sdl/translations/en.yml +9 -0
- data/lib/sdl/types.rb +19 -0
- data/lib/sdl/types/sdl_datetime.rb +10 -0
- data/lib/sdl/types/sdl_default_type.rb +13 -0
- data/lib/sdl/types/sdl_description.rb +10 -0
- data/lib/sdl/types/sdl_duration.rb +12 -0
- data/lib/sdl/types/sdl_number.rb +10 -0
- data/lib/sdl/types/sdl_string.rb +10 -0
- data/lib/sdl/types/sdl_type.rb +31 -0
- data/lib/sdl/types/sdl_url.rb +12 -0
- data/lib/sdl/util.rb +4 -0
- data/lib/sdl/util/documentation.rb +80 -0
- data/lib/sdl/util/nokogiri.rb +28 -0
- data/lib/sdl/util/verbs.rb +3 -0
- data/lib/sdl/version.rb +3 -0
- data/sdl-ng.gemspec +34 -0
- data/spec/documentation_spec.rb +64 -0
- data/spec/fact_type_instance_definition_spec.rb +188 -0
- data/spec/property_definitions_spec.rb +44 -0
- data/spec/service_compendium_spec.rb +90 -0
- data/spec/service_definition_spec.rb +81 -0
- data/spec/shared_test_compendium.rb +65 -0
- data/spec/spec_helper.rb +10 -0
- metadata +291 -0
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative 'exporters/xml_mapping'
|
2
|
+
require_relative 'exporters/exporter'
|
3
|
+
require_relative 'exporters/schema_exporter'
|
4
|
+
require_relative 'exporters/service_exporter'
|
5
|
+
require_relative 'exporters/xsd_schema_exporter'
|
6
|
+
require_relative 'exporters/xml_service_exporter'
|
7
|
+
require_relative 'exporters/rdf_mapping'
|
8
|
+
require_relative 'exporters/rdf_exporter'
|
9
|
+
require_relative 'exporters/markdown_service_exporter'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SDL
|
2
|
+
module Exporters
|
3
|
+
class Exporter
|
4
|
+
attr :compendium
|
5
|
+
attr :options
|
6
|
+
|
7
|
+
def initialize(compendium, options = {})
|
8
|
+
@compendium = compendium
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def export_to_file(path, content)
|
13
|
+
File.open(path, 'w') do |f|
|
14
|
+
f.write(content)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
require 'rdf/rdfxml'
|
3
|
+
|
4
|
+
module SDL
|
5
|
+
module Exporters
|
6
|
+
class RDFExporter < ServiceExporter
|
7
|
+
@@s = RDF::Vocabulary.new('http://www.open-service-compendium.org/')
|
8
|
+
|
9
|
+
def export_service(service)
|
10
|
+
graph = RDF::Graph.new
|
11
|
+
|
12
|
+
service.facts.each do |fact|
|
13
|
+
graph << [RDF::URI.new(service.uri), @@s["has_#{fact.class.local_name.underscore}"], RDF::URI.new(fact.uri)]
|
14
|
+
|
15
|
+
expand_properties(fact, graph)
|
16
|
+
end
|
17
|
+
|
18
|
+
graph.dump(:rdf)
|
19
|
+
end
|
20
|
+
|
21
|
+
def expand_properties(type_instance, graph)
|
22
|
+
type_instance.property_values.each do |property, value|
|
23
|
+
[value].flatten.each do |v|
|
24
|
+
graph << [RDF::URI.new(type_instance.uri), @@s["#{property.name.underscore}"], v.rdf_object] unless v.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
if property.type < SDL::Base::Type
|
28
|
+
[value].flatten.each do |v| expand_properties(v, graph) end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
[String, Fixnum, Nokogiri::XML::Element].each do |klass|
|
5
|
+
klass.class_eval do
|
6
|
+
def rdf_object
|
7
|
+
RDF::Literal.new(self)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module SDL
|
13
|
+
module Base
|
14
|
+
class Fact
|
15
|
+
class << self
|
16
|
+
def uri
|
17
|
+
"http://www.open-service-compendium.org/types/#{@local_name}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def uri
|
22
|
+
"#{service.uri}/#{self.class.local_name.underscore}-#{hash}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Type
|
27
|
+
class << self
|
28
|
+
def uri
|
29
|
+
"http://www.open-service-compendium.org/types/#{@local_name}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def uri
|
34
|
+
self.class.uri + '/' + hash.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def rdf_object
|
38
|
+
RDF::URI.new(uri)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Service
|
43
|
+
def uri
|
44
|
+
"http://www.open-service-compendium.org/services/#{@symbolic_name}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module SDL
|
2
|
+
module Base
|
3
|
+
class Property
|
4
|
+
def xsd_element_name
|
5
|
+
if multi?
|
6
|
+
@name.singularize
|
7
|
+
else
|
8
|
+
@name
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Type
|
14
|
+
class << self
|
15
|
+
def xsd_element_name
|
16
|
+
local_name.camelize(:lower)
|
17
|
+
end
|
18
|
+
|
19
|
+
def xsd_type_name
|
20
|
+
local_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def xsd_type_qname
|
24
|
+
'sdl:' + xsd_type_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Fact
|
30
|
+
class << self
|
31
|
+
def xsd_type_name
|
32
|
+
"#{local_name}Fact"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Types
|
39
|
+
module SDLType
|
40
|
+
module ClassMethods
|
41
|
+
def xml_type
|
42
|
+
if self < SDL::Base::Type
|
43
|
+
wrapped_type.xsd_type_name
|
44
|
+
else
|
45
|
+
'ns:string'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SDL
|
2
|
+
module Exporters
|
3
|
+
class XMLServiceExporter < ServiceExporter
|
4
|
+
def export_service(service)
|
5
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
6
|
+
xml.service('xmlns' => 'http://www.open-service-compendium.org') do
|
7
|
+
service.facts.each do |fact|
|
8
|
+
xml.send(fact.class.xsd_element_name + '_') do
|
9
|
+
serialize_type_instance fact, xml
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
builder.to_xml
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize_type_instance(type_instance, xml)
|
19
|
+
type_instance.property_values.each do |property, value|
|
20
|
+
[value].flatten.each do |v|
|
21
|
+
if v.class < SDL::Base::Type
|
22
|
+
xml.send(property.xsd_element_name + '_', (!value.is_a?(Array) && value.identifier) ? {'identifier' => value.identifier.to_s} : {}) do
|
23
|
+
v.annotations.each do |annotation|
|
24
|
+
xml.annotation annotation
|
25
|
+
end
|
26
|
+
xml.documentation v.documentation if (!value.is_a?(Array) && value.identifier)
|
27
|
+
serialize_type_instance(v, xml)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
xml.send(property.xsd_element_name + '_', v)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module SDL
|
5
|
+
module Exporters
|
6
|
+
##
|
7
|
+
# The XSD schema exporter creates an XML Schema Definition for consuming service descriptions using the XML provided
|
8
|
+
# by the XMLServiceExporter.
|
9
|
+
#
|
10
|
+
# The schema consists of the following main components:
|
11
|
+
# - The definition of the root node, i.e., a service. The service contains an arbitrary number of elements of
|
12
|
+
# service fact types.
|
13
|
+
# - The definition of service fact classes and SDL types
|
14
|
+
# - The definition of a type base, containing annotations and documentation
|
15
|
+
class XSDSchemaExporter < SchemaExporter
|
16
|
+
def export_schema
|
17
|
+
export_schema_xml.to_xml
|
18
|
+
end
|
19
|
+
|
20
|
+
def export_schema_xml
|
21
|
+
Nokogiri::XML::Builder.new do |xml|
|
22
|
+
xml['ns'].schema('xmlns' => 'http://www.open-service-compendium.org', 'targetNamespace' => 'http://www.open-service-compendium.org', 'xmlns:ns' => 'http://www.w3.org/2001/XMLSchema', 'elementFormDefault' => 'qualified') do
|
23
|
+
xml['ns'].element :name => 'service' do
|
24
|
+
document(xml, I18n.t('sdl.xml.service_root'))
|
25
|
+
xml['ns'].complexType do
|
26
|
+
xml['ns'].choice :maxOccurs => 'unbounded' do
|
27
|
+
@compendium.fact_classes.each do |fact_class|
|
28
|
+
xml['ns'].element :name => fact_class.xsd_element_name, :type => fact_class.xsd_type_name do
|
29
|
+
document(xml, fact_class.documentation)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
xml['ns'].complexType :name => 'SDLTypeBase' do
|
37
|
+
document(xml, I18n.t('sdl.xml.typebase'))
|
38
|
+
xml['ns'].choice do
|
39
|
+
xml['ns'].element :name => 'documentation', :minOccurs => 0, :maxOccurs => 'unbounded', :type => 'ns:string' do
|
40
|
+
document(xml, I18n.t('sdl.xml.documentation'))
|
41
|
+
end
|
42
|
+
xml['ns'].element :name => 'annotation', :minOccurs => 0, :maxOccurs => 'unbounded', :type => 'ns:string' do
|
43
|
+
document(xml, I18n.t('sdl.xml.annotation'))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
xml['ns'].attribute :name => 'identifier' do
|
47
|
+
document(xml, I18n.t('sdl.xml.identifier'))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
(@compendium.fact_classes + @compendium.types).each do |fact_class|
|
52
|
+
xml['ns'].complexType :name => fact_class.xsd_type_name do
|
53
|
+
document(xml, fact_class.documentation)
|
54
|
+
xml['ns'].complexContent do
|
55
|
+
xml['ns'].extension :base => fact_class.is_sub? ? fact_class.superclass.xsd_type_name : 'SDLTypeBase' do
|
56
|
+
unless fact_class.properties.empty?
|
57
|
+
xml['ns'].sequence do
|
58
|
+
fact_class.properties.each do |property|
|
59
|
+
extend_property(property, xml) do
|
60
|
+
document(xml, property.documentation)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Creates an xml element corresponding to the SDL property
|
74
|
+
def extend_property(property, xml)
|
75
|
+
if property.multi?
|
76
|
+
xml['ns'].element :name => property.name.singularize, :type => property.type.xml_type, :minOccurs => 0, :maxOccurs => 'unbounded' do
|
77
|
+
yield
|
78
|
+
end
|
79
|
+
else
|
80
|
+
xml['ns'].element :name => property.name, :type => property.type.xml_type, :minOccurs => 0 do
|
81
|
+
yield
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Shortcut for adding an XSD documentation annotation
|
87
|
+
def document(xml, documentation)
|
88
|
+
xml['ns'].annotation do
|
89
|
+
xml['ns'].documentation documentation
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'receivers/type_instance_receiver'
|
2
|
+
require_relative 'receivers/type_receiver'
|
3
|
+
require_relative 'receivers/fact_receiver'
|
4
|
+
require_relative 'receivers/service_receiver'
|
5
|
+
|
6
|
+
|
7
|
+
module SDL
|
8
|
+
module Receivers
|
9
|
+
#
|
10
|
+
def self.set_value(type_class, type_instance, *property_values, compendium)
|
11
|
+
property_values.zip(type_class.properties(true)).each do |value, property|
|
12
|
+
if(value.is_a?(Hash))
|
13
|
+
TypeInstanceReceiver.new(type_instance, compendium).send(value.keys.first.to_s, value.values.first)
|
14
|
+
else
|
15
|
+
raise "Specified value '#{value}' for non-existing property." unless property
|
16
|
+
|
17
|
+
TypeInstanceReceiver.new(type_instance, compendium).send(property.name, value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'verbs'
|
2
|
+
|
3
|
+
require_relative '../base/service'
|
4
|
+
|
5
|
+
module SDL
|
6
|
+
module Receivers
|
7
|
+
class ServiceReceiver
|
8
|
+
include ActiveSupport::Inflector
|
9
|
+
|
10
|
+
attr :service
|
11
|
+
attr :compendium
|
12
|
+
|
13
|
+
def initialize(sym, compendium)
|
14
|
+
@service = SDL::Base::Service.new(sym.to_s)
|
15
|
+
@compendium = compendium
|
16
|
+
|
17
|
+
compendium.fact_classes.each do |fact_class|
|
18
|
+
define_singleton_method("is_#{fact_class.local_name.underscore.verb.conjugate(:tense => :past, :person => :third, :plurality => :singular, :aspect => :perfective)}") do |*args, &block|
|
19
|
+
add_fact fact_class, *args, &block
|
20
|
+
end
|
21
|
+
|
22
|
+
define_singleton_method("has_#{fact_class.local_name.underscore}") do |*args, &block|
|
23
|
+
add_fact fact_class, *args, &block
|
24
|
+
end
|
25
|
+
|
26
|
+
define_singleton_method("#{fact_class.local_name.underscore}") do |*args, &block|
|
27
|
+
add_fact fact_class, *args, &block
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def add_fact(fact_class, *property_values, &block)
|
34
|
+
fact_instance = fact_class.new
|
35
|
+
fact_instance.service = @service
|
36
|
+
|
37
|
+
SDL::Receivers.set_value(fact_class, fact_instance, *property_values, @compendium)
|
38
|
+
|
39
|
+
if block_given?
|
40
|
+
SDL::Receivers::TypeInstanceReceiver.new(fact_instance, @compendium).instance_eval &block
|
41
|
+
end
|
42
|
+
|
43
|
+
@service.facts << fact_instance
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Catches calls to methods named similarily to possible predefined type instances
|
48
|
+
def method_missing(name, *args)
|
49
|
+
possible_type_instances = @compendium.type_instances.map{|k, v| v[name]}.select{|v| v != nil}
|
50
|
+
|
51
|
+
unless possible_type_instances.nil? || possible_type_instances.empty?
|
52
|
+
if possible_type_instances.length > 1
|
53
|
+
raise Exception.new("Multiple possibilities for #{name} in #{caller[0]}")
|
54
|
+
else
|
55
|
+
possible_type_instances[0]
|
56
|
+
end
|
57
|
+
else
|
58
|
+
raise Exception.new("I do not know what to do with '#{name}' in #{caller[0]}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module SDL
|
4
|
+
module Receivers
|
5
|
+
##
|
6
|
+
# Receiver for setting the properties of Type instances
|
7
|
+
class TypeInstanceReceiver
|
8
|
+
attr_accessor :instance
|
9
|
+
|
10
|
+
attr_accessor :compendium
|
11
|
+
|
12
|
+
##
|
13
|
+
# When initialized for a fact or type instance, the receiver creates singleton methods on itself for all
|
14
|
+
# properties.
|
15
|
+
def initialize(instance, compendium)
|
16
|
+
@instance = instance
|
17
|
+
@compendium = compendium
|
18
|
+
|
19
|
+
instance.class.properties(true).each do |property|
|
20
|
+
if property.single?
|
21
|
+
# Single valued properties are set by their name
|
22
|
+
define_singleton_method property.name do |value = nil, &block|
|
23
|
+
if value.is_a? Symbol
|
24
|
+
value = compendium.type_instances[property.type][value] || raise("Could not find instance :#{value.to_s} in predefined #{property.type.name} types")
|
25
|
+
end
|
26
|
+
|
27
|
+
instance.send "#{property.name}=", value
|
28
|
+
end
|
29
|
+
else
|
30
|
+
# Multi-valued properties are added to by their singular name
|
31
|
+
define_singleton_method property.name.singularize do |*property_values, &block|
|
32
|
+
existing_list = instance.send "#{property.name}"
|
33
|
+
|
34
|
+
unless property_values.empty?
|
35
|
+
# If there is just one parameter for a multi-valued property setter
|
36
|
+
if property_values.length == 1
|
37
|
+
# It could be a symbol, which would resolve to a predefined type instance of the same name
|
38
|
+
if property_values[0].is_a?(Symbol)
|
39
|
+
predefined_value = compendium.type_instances[property.type][property_values[0]]
|
40
|
+
|
41
|
+
raise "Could not find instance :#{property_values[0]} in predefined #{property.type.name} types" unless predefined_value
|
42
|
+
|
43
|
+
existing_list << compendium.type_instances[property.type][property_values[0]]
|
44
|
+
# Or better: it could already be an instance of the type - e.g. when using the implemented #method_mssing
|
45
|
+
elsif property_values[0].is_a? property.type
|
46
|
+
existing_list << property_values[0]
|
47
|
+
end
|
48
|
+
else
|
49
|
+
new_list_item = property.type.new
|
50
|
+
|
51
|
+
SDL::Receivers.set_value(property.type, new_list_item, *property_values, @compendium)
|
52
|
+
|
53
|
+
self.class.new(new_list_item, @compendium).instance_exec(&block) unless block.nil?
|
54
|
+
|
55
|
+
existing_list << new_list_item
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def annotation(value)
|
64
|
+
@instance.annotations << value
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Catches calls to methods named similarily to possible predefined type instances
|
69
|
+
def method_missing(name, *args)
|
70
|
+
# Possible type instances are all types of properties of properties of this instance ...
|
71
|
+
possible_type_classes = @instance.class.properties.map(&:type).map(&:properties).flatten.map(&:type).select{|type| type.wrapped_type < SDL::Base::Type}
|
72
|
+
|
73
|
+
# ... and the types of multi-value instances
|
74
|
+
possible_type_classes.concat(@instance.class.properties.find_all{|p| p.multi?}.map(&:type))
|
75
|
+
|
76
|
+
possible_type_instances = @compendium.type_instances.select{|k, v| possible_type_classes.include?(k)}.map{|k, v| v[name]}.select{|v| v != nil}
|
77
|
+
|
78
|
+
unless possible_type_instances.nil? || possible_type_instances.empty?
|
79
|
+
possible_type_instances[0]
|
80
|
+
else
|
81
|
+
raise Exception.new("I do not know what to do with '#{name}' in #{caller[0]}")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|