diff --git a/.ruby-version b/.ruby-version
index 8bbe6cf..ecd7ee5 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.2
+2.5.8
diff --git a/lib/frodata/schema.rb b/lib/frodata/schema.rb
index 4c6cb44..0b34000 100644
--- a/lib/frodata/schema.rb
+++ b/lib/frodata/schema.rb
@@ -137,7 +137,7 @@ def process_property_from_xml(property_xml)
property_type, value_type = property_type.split(/\(|\)/)
if property_type == 'Collection'
klass = ::FrOData::Properties::Collection
- property_options.merge(value_type: value_type)
+ property_options.merge!(value_type: value_type)
else
klass = ::FrOData::PropertyRegistry[property_type]
end
diff --git a/lib/frodata/schema/enum_type.rb b/lib/frodata/schema/enum_type.rb
index c3151c3..641028e 100644
--- a/lib/frodata/schema/enum_type.rb
+++ b/lib/frodata/schema/enum_type.rb
@@ -46,18 +46,23 @@ def namespace
# @return [Hash]
def members
@members ||= collect_members
+ end
+
+ def annotated_members
+ @annotated_members ||= collect_annotated_members
end
# Returns the property class that implements this `EnumType`.
# @return [Class < FrOData::Properties::Enum]
def property_class
- @property_class ||= lambda { |type, members, is_flags|
+ @property_class ||= lambda { |type, members, annotated_members, is_flags|
klass = Class.new ::FrOData::Properties::Enum
klass.send(:define_method, :type) { type }
klass.send(:define_method, :members) { members }
+ klass.send(:define_method, :annotated_members) { annotated_members }
klass.send(:define_method, :is_flags?) { is_flags }
klass
- }.call(type, members, is_flags?)
+ }.call(type, members, annotated_members, is_flags?)
end
# Returns the value of the requested member.
@@ -89,6 +94,18 @@ def collect_members
member_value = member_xml.attributes['Value'].andand.value.andand.to_i
[member_value || index, member_name]
end]
+ end
+
+ def collect_annotated_members
+ Hash[type_definition.xpath('./Member').map.with_index do |member_xml, index|
+ member_name = member_xml.attributes['Name'].value
+ member_value = member_xml.attributes['Value'].andand.value.andand.to_i
+ annotation = nil
+ if member_xml.element_children.count > 0
+ annotation = member_xml.element_children.last.attribute('String').value
+ end
+ [member_value || index, {name: member_name, annotation: annotation}]
+ end]
end
end
end
diff --git a/spec/fixtures/files/metadata.xml b/spec/fixtures/files/metadata.xml
index 25d9e10..0329e24 100644
--- a/spec/fixtures/files/metadata.xml
+++ b/spec/fixtures/files/metadata.xml
@@ -9,6 +9,8 @@
+
+
@@ -18,6 +20,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spec/frodata/entity/shared_examples.rb b/spec/frodata/entity/shared_examples.rb
index 0f9b24c..92f9b91 100644
--- a/spec/frodata/entity/shared_examples.rb
+++ b/spec/frodata/entity/shared_examples.rb
@@ -15,7 +15,7 @@
it { expect(subject.get_property('ReleaseDate')).to be_a(FrOData::Properties::DateTimeOffset) }
it { expect(subject.get_property('DiscontinuedDate')).to be_a(FrOData::Properties::DateTimeOffset) }
it { expect(subject.get_property('Rating')).to be_a(FrOData::Properties::Integer) }
- it { expect(subject.get_property('Price')).to be_a(FrOData::Properties::Double) }
+ it { expect(subject.get_property('Price')).to be_a(FrOData::Properties::Float) }
# Navigation property proxies
it { expect(subject.get_property('Categories')).to be_a(FrOData::NavigationProperty::Proxy)}
diff --git a/spec/frodata/property_collection_spec.rb b/spec/frodata/property_collection_spec.rb
new file mode 100644
index 0000000..80149f4
--- /dev/null
+++ b/spec/frodata/property_collection_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe FrOData::Property do
+ let(:service) do
+ FrOData::Service.new('http://services.odata.org/V4/OData/OData.svc', metadata_file: metadata_file)
+ end
+ let(:metadata_file) { 'spec/fixtures/files/metadata.xml' }
+
+ describe '#type' do
+ it 'returns the right type' do
+ t = service.schemas['ODataDemo'].properties_for_entity('Product')['ProductStatus'].type
+ expect(t).to eq('ODataDemo.ProductStatus')
+
+ t = service.schemas['ODataDemo'].properties_for_entity('Product')['EthicalAttributes'].type
+ expect(t).to eq('Collection(ODataDemo.EthicalAttribute)')
+ end
+ end
+end
diff --git a/spec/frodata/schema/annotated_enum_type_spec.rb b/spec/frodata/schema/annotated_enum_type_spec.rb
new file mode 100644
index 0000000..967a123
--- /dev/null
+++ b/spec/frodata/schema/annotated_enum_type_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe FrOData::Schema::EnumType, vcr: {cassette_name: 'schema/enum_type_specs'} do
+ before(:example) do
+ FrOData::Service.new('http://services.odata.org/V4/OData/OData.svc', name: 'ODataDemo', metadata_file: metadata_file)
+ end
+
+ let(:metadata_file) { 'spec/fixtures/files/metadata.xml' }
+ let(:service) { FrOData::ServiceRegistry['ODataDemo'] }
+
+ let(:enum_type) { service.enum_types['ODataDemo.Vertical'] }
+ let(:subject) { enum_type.property_class.new('Vertical', nil) }
+
+ describe 'is properly parsed from service metadata' do
+ it { expect(enum_type.name).to eq('Vertical') }
+ it { expect(enum_type.namespace).to eq('ODataDemo') }
+ it { expect(enum_type.type).to eq('ODataDemo.Vertical') }
+ it { expect(enum_type.is_flags?).to eq(false) }
+ it { expect(enum_type.underlying_type).to eq('Edm.Int64') }
+ it { expect(enum_type.members.values).to eq(%w{OutdoorsAndNature HomeAndOffice}) }
+ it {
+ expect(enum_type.annotated_members).to eq({
+ 1 => { name: 'OutdoorsAndNature', annotation: 'Outdoor and Nature Products' },
+ 2 => { name: 'HomeAndOffice', annotation: 'Home and Office Products' }
+ })
+ }
+ end
+
+ # Check property instance inheritance hierarchy
+ it { expect(subject).to be_a(FrOData::Property) }
+ it { expect(subject).to be_a(FrOData::Properties::Enum) }
+
+ it { expect(subject).to respond_to(:name) }
+ it { expect(subject).to respond_to(:type) }
+ it { expect(subject).to respond_to(:members) }
+
+end
diff --git a/spec/frodata/schema_spec.rb b/spec/frodata/schema_spec.rb
index 6f592ed..8eac1ab 100644
--- a/spec/frodata/schema_spec.rb
+++ b/spec/frodata/schema_spec.rb
@@ -10,7 +10,7 @@
let(:entity_types) { %w{Product FeaturedProduct ProductDetail Category Supplier Person Customer Employee PersonDetail Advertisement} }
let(:complex_types) { %w{Address} }
- let(:enum_types) { %w{ProductStatus} }
+ let(:enum_types) { %w{Vertical EthicalAttribute ProductStatus} }
describe '#namespace' do
it { expect(subject).to respond_to(:namespace) }
@@ -43,7 +43,7 @@
describe '#enum_types' do
it { expect(subject).to respond_to(:enum_types) }
- it { expect(subject.enum_types.size).to eq(1) }
+ it { expect(subject.enum_types.size).to eq(3) }
it { expect(subject.enum_types.keys).to eq(enum_types)}
end
diff --git a/spec/frodata/service_spec.rb b/spec/frodata/service_spec.rb
index c6a294d..7de7f6e 100644
--- a/spec/frodata/service_spec.rb
+++ b/spec/frodata/service_spec.rb
@@ -159,8 +159,8 @@
describe '#enum_types' do
it { expect(subject).to respond_to(:enum_types) }
- it { expect(subject.enum_types.size).to eq(1) }
- it { expect(subject.enum_types.keys).to eq(['ODataDemo.ProductStatus'])}
+ it { expect(subject.enum_types.size).to eq(3) }
+ it { expect(subject.enum_types.keys).to eq(['ODataDemo.Vertical', 'ODataDemo.EthicalAttribute', 'ODataDemo.ProductStatus'])}
end
describe '#namespace' do
@@ -190,6 +190,8 @@
ID
Name
Description
+ Vertical
+ EthicalAttributes
ReleaseDate
DiscontinuedDate
Rating