occi 2.2.2 → 2.3.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/.yardopts CHANGED
@@ -1 +1 @@
1
- --title "Documentation of the OCCI gem" --markup markdown
1
+ --title "Documentation of the OCCI gem" --markup markdown --private
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source :rubygems
4
4
  gem "json"
5
5
  gem "antlr3"
6
6
  gem "hashie"
7
- gem "uuidtools"
7
+ gem "uuidtools", ">=2.1.3"
8
8
  gem "nokogiri"
9
9
  gem "builder"
10
10
  gem "activesupport"
@@ -31,7 +31,7 @@ GEM
31
31
  multi_json (~> 1.0)
32
32
  simplecov-html (~> 0.5.3)
33
33
  simplecov-html (0.5.3)
34
- uuidtools (2.1.2)
34
+ uuidtools (2.1.3)
35
35
  yard (0.7.5)
36
36
  yard-sinatra (1.0.0)
37
37
  yard (~> 0.7)
@@ -51,6 +51,6 @@ DEPENDENCIES
51
51
  rspec
52
52
  rspec-http
53
53
  simplecov
54
- uuidtools
54
+ uuidtools (>= 2.1.3)
55
55
  yard
56
56
  yard-sinatra
data/README.md CHANGED
@@ -17,24 +17,11 @@ Installation
17
17
 
18
18
  gem install occi
19
19
 
20
- ### Latest version
21
-
22
- Checkout latest version from GIT:
23
-
24
- git clone git://github.com/gwdg/rOCCI.git
25
-
26
- Change to rOCCI folder
27
-
28
- cd rOCCI
29
-
30
- Install dependencies for deployment
31
-
32
- bundle install --deployment
33
-
34
20
  Usage
35
21
  -----
36
22
 
37
- First require the gem
23
+ First require the gem, for Ruby 1.8.7 you also have to require rubygems
24
+ require 'rubygems'
38
25
  require 'occi'
39
26
 
40
27
  ### Client
@@ -43,7 +30,7 @@ The OCCI gem includes a Client to simplify the usage of an OCCI endpoint.
43
30
 
44
31
  To connect to an OCCI endpoint/server (e.g. running at http://localhost:3000/ ) use
45
32
 
46
- client = OCCI::Client.new('http://localhost:3000')
33
+ client = OCCI::Client.new('http://occi.cloud.gwdg.de:3300')
47
34
 
48
35
  All available categories are automatically registered to the OCCI model during client initialization. You can get them via
49
36
 
@@ -112,11 +99,35 @@ the message header. As the text/plain and text/occi media type do not clearly di
112
99
  category and a message with an entity which has a kind, it has to be specified if the message contains a category (e
113
100
  .g. for user defined mixins)
114
101
 
115
- OCCI messages can be parsed for example like
102
+ OCCI messages can be parsed to an OCCI collection for example like
116
103
 
117
104
  media_type = text/plain
118
105
  body = %Q|Category: compute; scheme="http://schemas.ogf.org/occi/infrastructure#"; class="kind"|
119
- OCCI::Parser.parse(media_type,body)
106
+ collection=OCCI::Parser.parse(media_type,body)
107
+
108
+ ### Parsing OVF / OVA files
109
+
110
+ Parsing of OVF/OVA files is partly supported and will be improved in future versions.
111
+
112
+ The example in [DMTF DSP 2021](http://www.dmtf.org/sites/default/files/standards/documents/DSP2021_1.0.0.tar) is
113
+ bundled with rOCCI and can be parsed to an OCCI collection with
114
+
115
+ require 'open-uri'
116
+ ova=open 'https://raw.github.com/gwdg/rOCCI/master/spec/occi/test.ova'
117
+ collection=OCCI::Parser.ova(ova.read)
118
+
119
+ Currently only the following entries of OVF files are parsed
120
+
121
+ * File in References
122
+ * Disk in the DiskSection
123
+ * Network in the NetworkSection
124
+ * in the VirutalSystemSection:
125
+ ** Info
126
+ ** in the VirtualHardwareSection the items regarding
127
+ *** Processor
128
+ *** Memory
129
+ *** Ethernet Adapter
130
+ *** Parallel port
120
131
 
121
132
  ### Using the OCCI model
122
133
 
@@ -125,6 +136,13 @@ The OCCI gem includes all OCCI Core classes necessary to handly arbitrary OCCI o
125
136
  Changelog
126
137
  ---------
127
138
 
139
+ ### Version 2.3
140
+
141
+ * OCCI objects are now initialized with a list of attributes instead of a hash. Thus it is easier to check which
142
+ attributes are expected by a class and helps prevent errors.
143
+ * Parsing of a subset of the OVF specification is supported. Further parts of the specification will be covered in
144
+ future versions of rOCCI.
145
+
128
146
  ### Version 2.2
129
147
 
130
148
  OCCI Client added. The client simplifies the execution of OCCI commands and provides shortcuts for often used steps.
@@ -144,6 +162,18 @@ Version 1.X of the OCCI gem has been developed by retr0h and served as a simple
144
162
  Development
145
163
  -----------
146
164
 
165
+ Checkout latest version from GIT:
166
+
167
+ git clone git://github.com/gwdg/rOCCI.git
168
+
169
+ Change to rOCCI folder
170
+
171
+ cd rOCCI
172
+
173
+ Install dependencies for deployment
174
+
175
+ bundle install --deployment
176
+
147
177
  ### Code Documentation
148
178
 
149
179
  [Code Documentation for rOCCI by YARD](http://rubydoc.info/github/gwdg/rOCCI/)
@@ -8,22 +8,15 @@ module OCCI
8
8
  headers 'Accept' => 'application/occi+json'
9
9
 
10
10
  attr_reader :endpoint
11
-
12
- attr_reader :compute
13
- attr_reader :storage
14
- attr_reader :network
11
+ attr_reader :model
15
12
 
16
13
  def initialize(endpoint)
17
- @endpoint = endpoint
18
- collection = OCCI::Collection.new(get_model)
19
- OCCI::Model.register_collection(collection)
20
- @compute = OCCI::Model.get_by_id('http://schemas.ogf.org/occi/infrastructure#compute')
21
- @storage = OCCI::Model.get_by_id('http://schemas.ogf.org/occi/infrastructure#storage')
22
- @network = OCCI::Model.get_by_id('http://schemas.ogf.org/occi/infrastructure#network')
14
+ @endpoint = endpoint
15
+ @model = OCCI::Model.new(OCCI::Collection.new(get_model))
23
16
  end
24
17
 
25
18
  def get_model
26
- self.class.get(endpoint + '/-/')
19
+ get(@endpoint + '/-/').body
27
20
  end
28
21
 
29
22
  def post_mixin
@@ -60,15 +53,15 @@ module OCCI
60
53
  resource.links = []
61
54
  resources_to_link.each do |res|
62
55
  link = OCCI::Link.new
63
- link.kind = 'http://schemas.ogf.org/occi/infrastructure#storagelink' if OCCI::Model.get_by_id(res.kind).related_to? 'http://schemas.ogf.org/occi/infrastructure#storage'
64
- link.kind = 'http://schemas.ogf.org/occi/infrastructure#networkinterface' if OCCI::Model.get_by_id(res.kind).related_to? 'http://schemas.ogf.org/occi/infrastructure#network'
56
+ link.kind = 'http://schemas.ogf.org/occi/infrastructure#storagelink' if @model.get_by_id(res.kind).related_to? 'http://schemas.ogf.org/occi/infrastructure#storage'
57
+ link.kind = 'http://schemas.ogf.org/occi/infrastructure#networkinterface' if @model.get_by_id(res.kind).related_to? 'http://schemas.ogf.org/occi/infrastructure#network'
65
58
  link.titlte "Link to #{res.title}"
66
59
  link.target = res.location
67
60
  resource.links << link
68
61
  end
69
62
  resource.check
70
63
  collection = OCCI::Collection.new(:resources => [resource])
71
- self.class.post(@endpoint + kind.location, { :body => collection.to_json, :headers => { 'Content-Type' => 'application/occi+json', 'Accept' => 'text/uri-list' }, :format => 'text/plain' }).to_s
64
+ self.class.post(@endpoint + kind.location, { :body => collection.to_json, :headers => { 'Content-Type' => 'application/occi+json', 'Accept' => 'text/uri-list' }, :format => 'text/plain' }).body
72
65
  end
73
66
 
74
67
  def delete_resources
@@ -84,7 +77,7 @@ module OCCI
84
77
 
85
78
 
86
79
  def get_compute_list
87
- self.class.get(@endpoint + @compute.location, {:headers => { 'Accept' => 'text/uri-list' }, :format => 'text/plain'}).split("\n").compact
80
+ self.class.get(@endpoint + @compute.location, { :headers => { 'Accept' => 'text/uri-list' }, :format => 'text/plain' }).split("\n").compact
88
81
  end
89
82
 
90
83
  def get_compute_resources
@@ -148,7 +141,7 @@ module OCCI
148
141
  def get_attributes(categories)
149
142
  attributes = Hashie::Mash.new
150
143
  [categories].flatten.each do |category|
151
- category = OCCI::Model.get_by_id(category) if category.kind_of? String
144
+ category = @model.get_by_id(category) if category.kind_of? String
152
145
  attributes.merge! category.attributes.combine_with_defaults
153
146
  end
154
147
  attributes
@@ -157,11 +150,55 @@ module OCCI
157
150
  def get_attribute_definitions(categories)
158
151
  definitions = OCCI::Core::AttributeProperties.new
159
152
  [categories].flatten.each do |category|
160
- category = OCCI::Model.get_by_id(category) if category.kind_of? String
153
+ category = @model.get_by_id(category) if category.kind_of? String
161
154
  definitions.merge! category.attributes
162
155
  end
163
156
  definitions
164
157
  end
165
158
 
159
+ private
160
+
161
+ def get(path, collection=nil)
162
+ accept = head(path).headers['accept']
163
+ if accept.include? 'application/occi+json'
164
+ if collection
165
+ response = self.class.get(path, :body => collection.to_json)
166
+ else
167
+ response = self.class.get(path)
168
+ end
169
+ OCCI::Parser.parse(response.env['Content-Type'], response.body)
170
+ else
171
+ if collection
172
+ response = self.class.get(path, :headers => { 'Accept' => 'text/plain', 'Content-Type' => 'text/occi', 'Category ' => collection.categories.collect { |category| category.to_text }.join(','), 'X-OCCI-Attributes' => collection.entities.collect { |entity| entity.attributes.combine.collect { |k, v| k + '=' + v } }.join(',') })
173
+ else
174
+ response = self.class.get(path, :headers => { 'Accept' => 'text/plain' })
175
+ end
176
+ OCCI::Parser.parse(response.env['Content-Type'], response.body, true)
177
+ end
178
+ end
179
+
180
+ def post(path, collection)
181
+ accept = self.class.head(path).headers['accept']
182
+ if accept.include? 'application/occi+json'
183
+ self.class.post(path, :body => collection.to_json)
184
+ else
185
+ self.class.post(path, { :body => collection.to_text, :headers => { 'Accept' => 'text/plain', 'Content-Type' => 'text/plain' } })
186
+ end
187
+ end
188
+
189
+ def put(path, collection)
190
+ accept = self.class.head(path).headers['accept']
191
+ if accept.include? 'application/occi+json'
192
+ self.class.put(path, :body => collection.to_json)
193
+ else
194
+ self.class.put(path, { :body => collection.to_text, :headers => { 'Accept' => 'text/plain', 'Content-Type' => 'text/plain' } })
195
+ end
196
+ end
197
+
198
+ def delete(path, collection)
199
+ accept = self.class.head(path).headers['accept']
200
+ self.class.delete(path)
201
+ end
202
+
166
203
  end
167
204
  end
@@ -1,4 +1,5 @@
1
1
  require 'hashie/mash'
2
+ require 'active_support/json'
2
3
 
3
4
  module OCCI
4
5
  class Collection
@@ -18,11 +19,11 @@ module OCCI
18
19
  @actions = []
19
20
  @resources = []
20
21
  @links = []
21
- @kinds = collection.kinds.collect { |kind| OCCI::Core::Kind.new(kind) } if collection.kinds.instance_of? Array
22
- @mixins = collection.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin) } if collection.mixins.instance_of? Array
23
- @actions = collection.actions.collect { |action| OCCI::Core::Action.new(action) } if collection.actions.instance_of? Array
24
- @resources = collection.resources.collect { |resource| OCCI::Core::Resource.new(resource) } if collection.resources.instance_of? Array
25
- @links = collection.links { |link| OCCI::Core::Link.new(link) } if collection.links.instance_of? Array
22
+ @kinds = collection.kinds.collect { |kind| OCCI::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) } if collection.kinds.instance_of? Array
23
+ @mixins = collection.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) } if collection.mixins.instance_of? Array
24
+ @actions = collection.actions.collect { |action| OCCI::Core::Action.new(action.scheme, action.term, action.title, action.attributes) } if collection.actions.instance_of? Array
25
+ @resources = collection.resources.collect { |resource| OCCI::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.links) } if collection.resources.instance_of? Array
26
+ @links = collection.links { |link| OCCI::Core::Link.new(link.kind, link.mixins, link.attributes) } if collection.links.instance_of? Array
26
27
  end
27
28
 
28
29
  # @return [Array] categories combined list of all kinds, mixins and actions
@@ -35,12 +36,29 @@ module OCCI
35
36
  @resources + @links
36
37
  end
37
38
 
39
+ # @return [true,false] true if collection is empty, false otherwise
38
40
  def empty?
39
41
  @kinds.empty? && @mixins.empty? && @actions.empty? && @resources.empty? && @links.empty?
40
42
  end
41
43
 
42
- def to_json(options = { })
43
- { :kinds => @kinds, :mixins => @mixins, :actions => @actions, :resources => @resources, :links => @links }.to_json
44
+ # @return [Hashie::Mash] returns collection as Hashie::Mash which can be converted to json
45
+ def as_json(options = { })
46
+ collection = Hashie::Mash.new
47
+ collection.kinds = @kinds.collect { |kind| kind.as_json } if @kinds.any?
48
+ collection.mixins = @mixins.collect { |mixin| mixin.as_json } if @mixins.any?
49
+ collection.actions = @actions.collect { |action| action.as_json } if @actions.any?
50
+ collection.resources = @resources.collect { |resource| resource.as_json } if @resources.any?
51
+ collection.links = @links.collect { |link| link.as_json } if @links.any?
52
+ collection
53
+ end
54
+
55
+ def to_text
56
+ body = ""
57
+ body << self.categories.collect { |category| category.to_text }.join("\n")
58
+ body << "\n" if self.categories.any?
59
+ raise "Only one entity allowed for rendering to plain text" if body.entities.size > 1
60
+ body << self.entities.collect {|entity| entity.to_text}.join("\n")
61
+ body
44
62
  end
45
63
 
46
64
  end
@@ -3,6 +3,13 @@ require 'occi/core/category'
3
3
  module OCCI
4
4
  module Core
5
5
  class Action < OCCI::Core::Category
6
+
7
+ def to_text
8
+ text = super
9
+ text << ';attributes=' + @attributes.combine.join(' ').inspect if @attributes.any?
10
+ text
11
+ end
12
+
6
13
  end
7
14
  end
8
15
  end
@@ -23,7 +23,7 @@ module OCCI
23
23
  self[key].combine.each { |attr| array << key + '.' + attr }
24
24
  end
25
25
  end
26
- return array
26
+ array
27
27
  end
28
28
 
29
29
  def combine_with_defaults
@@ -35,7 +35,7 @@ module OCCI
35
35
  self[key].combine_with_defaults.each { |k,v| hash[key + '.' + k] = v }
36
36
  end
37
37
  end
38
- return hash
38
+ hash
39
39
  end
40
40
 
41
41
  end
@@ -13,14 +13,14 @@ module OCCI
13
13
  hash[key] = self[key]
14
14
  end
15
15
  end
16
- return hash
16
+ hash
17
17
  end
18
18
 
19
19
  def self.split(attributes)
20
20
  attribute = Attributes.new
21
21
  attributes.each do |name,value|
22
22
  puts name
23
- key, dot, rest = name.partition('.')
23
+ key, _, rest = name.partition('.')
24
24
  if rest.empty?
25
25
  attribute[key] = value
26
26
  else
@@ -1,41 +1,61 @@
1
- require 'json'
1
+ require 'active_support/json'
2
+ require 'active_support/inflector'
2
3
  require 'hashie/mash'
3
4
 
4
5
  module OCCI
5
6
  module Core
6
- class Category < Hashie::Mash
7
+ class Category
7
8
 
8
- def initialize(category=nil, default = nil)
9
- category.attributes = OCCI::Core::AttributeProperties.new(category.attributes) if category
10
- super(category, default)
11
- end
9
+ attr_accessor :scheme, :term, :title, :attributes
12
10
 
13
- def convert_value(val, duping=false) #:nodoc:
14
- case val
15
- when self.class
16
- val.dup
17
- when ::Hash
18
- val = val.dup if duping
19
- self.class.subkey_class.new.merge(val) unless val.kind_of?(Hashie::Mash)
20
- val
21
- when Array
22
- val.collect { |e| convert_value(e) }
23
- else
24
- val
25
- end
11
+ # @param [String ] scheme
12
+ # @param [String] term
13
+ # @param [String] title
14
+ # @param [OCCI::Core::AttributeProperties] attributes
15
+ def initialize(scheme, term, title=nil, attributes=nil)
16
+ @scheme = scheme
17
+ @term = term
18
+ @title = title
19
+ @attributes = OCCI::Core::AttributeProperties.new(attributes)
26
20
  end
27
21
 
22
+ # @return [String] Type identifier of the category
28
23
  def type_identifier
29
- regular_reader("scheme") + regular_reader("term")
24
+ @scheme + @term
25
+ end
26
+
27
+ # converts and adds supplied attributes to attributes of the category
28
+ # @param [Hash] attributes
29
+ # @return [OCCI::Core::AttributeProperties] attributes hash converted to attribute properties
30
+ def attributes=(attributes)
31
+ @attributes = OCCI::Core::AttributeProperties.new(attributes)
30
32
  end
31
33
 
32
- def related_to?(category_id)
34
+ # check if category is related to another category
35
+ # @param [String] category_id Type identifier of a related category
36
+ # @return [true,false] true if category is related to category_id else false
37
+ def related_to?(category_id, model)
33
38
  self.related.each do |rel_id|
34
- return true if rel_id == category_id || OCCI::Model.get_by_id(rel_id).related_to?(category_id)
35
- end if self.related
39
+ return true if rel_id == category_id || model.get_by_id(rel_id).related_to?(category_id, model)
40
+ end if self.class.method_defined? 'related'
36
41
  false
37
42
  end
38
43
 
44
+ def as_json(options={ })
45
+ category = Hashie::Mash.new
46
+ category.scheme = @scheme if @scheme
47
+ category.term = @term if @term
48
+ category.title = @title if @title
49
+ category.attributes = @attributes if @attributes.any?
50
+ category
51
+ end
52
+
53
+ def to_text
54
+ text = @term + ';scheme=' + @scheme.inspect + ';class=' + self.class.name.demodulize.downcase.inspect
55
+ text << ';title=' + @title.inspect if @title
56
+ text
57
+ end
58
+
39
59
  end
40
60
  end
41
61
  end
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'uuidtools'
3
3
  require 'hashie/mash'
4
+ require 'active_support/json'
4
5
  require 'occi/model'
5
6
  require 'occi/core/attributes'
6
7
  require 'occi/core/kind'
@@ -8,90 +9,89 @@ require 'occi/core/attribute_properties'
8
9
 
9
10
  module OCCI
10
11
  module Core
11
- class Entity < Hashie::Mash
12
-
13
- # Define appropriate kind
14
- def self.register
15
- data = Hashie::Mash.new
16
- data[:term] = "entity"
17
- data[:scheme] = "http://schemas.ogf.org/occi/core#"
18
- data[:title] = "Entity"
19
- data.attributes!.occi!.core!.id!.type = "string"
20
- data.attributes!.occi!.core!.id!.pattern = "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
21
- data.attributes!.occi!.core!.id!.required = false
22
- data.attributes!.occi!.core!.id!.mutable = false
23
- data.attributes!.occi!.core!.title!.type = "string"
24
- data.attributes!.occi!.core!.title!.pattern = ".*"
25
- data.attributes!.occi!.core!.title!.required = false
26
- data.attributes!.occi!.core!.title!.mutable = true
27
-
28
- kind = OCCI::Core::Kind.new(data)
29
- OCCI::Model.register(kind)
30
- end
12
+ class Entity
31
13
 
32
- def initialize(entity=nil, default = nil)
33
- super(entity, default)
34
- self.check
35
- end
14
+ attr_accessor :kind, :mixins, :attributes
36
15
 
37
- def id
38
- self[:id] ||= self.attributes!.occi!.core!.id if self.attributes!.occi!.core
39
- return self[:id]
40
- end
16
+ # @return [OCCI::Core::Kind] kind definition of Entity type
17
+ def self.kind_definition
18
+ kind = OCCI::Core::Kind.new('http://schemas.ogf.org/occi/core#', 'entity')
41
19
 
42
- def id=(id)
43
- self[:id] = id
44
- self.attributes ||= OCCI::Core::Attributes.new
45
- self.attributes!.occi!.core!.id = id
20
+ kind.title = "Entity"
21
+
22
+ kind.attributes.occi!.core!.id!.type = "string"
23
+ kind.attributes.occi!.core!.id!.pattern = "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
24
+ kind.attributes.occi!.core!.id!.required = false
25
+ kind.attributes.occi!.core!.id!.mutable = false
26
+
27
+ kind.attributes.occi!.core!.title!.type = "string"
28
+ kind.attributes.occi!.core!.title!.pattern = ".*"
29
+ kind.attributes.occi!.core!.title!.required = false
30
+ kind.attributes.occi!.core!.title!.mutable = true
31
+
32
+ kind
46
33
  end
47
34
 
48
- def title
49
- self[:title] ||= self.attributes!.occi!.core!.title if self.attributes!.occi!.core
50
- return self[:title]
35
+ # @param [String] kind
36
+ # @param [String] mixins
37
+ # @param [OCCI::Core::Attributes] attributes
38
+ def initialize(kind, mixins=nil, attributes=nil)
39
+ @kind = kind
40
+ @mixins = mixins.to_a
41
+ @attributes = OCCI::Core::Attributes.new(attributes)
42
+ self.id = UUIDTools::UUID.timestamp_create.to_s
51
43
  end
52
44
 
53
- def title=(title)
54
- self[:title] = title
55
- self.attributes ||= OCCI::Core::Attributes.new
56
- self.attributes!.occi!.core!.title = title
45
+ # set id for entity
46
+ # @param [UUIDTools::UUID] id
47
+ def id=(id)
48
+ @attributes.occi!.core!.id = id
57
49
  end
58
50
 
59
- def location
60
- '/' + OCCI::Model.get_by_id(self.kind).term + '/' + self.id if self.kind
51
+ # @return [UUIDTools::UUID] id of the entity
52
+ def id
53
+ @attributes.occi!.core!.id
61
54
  end
62
55
 
63
- def type_identifier
64
- OCCI::Model.get_by_id(self.kind).type_identifier
56
+ # @return [String] location of the entity
57
+ def location
58
+ '/' + @kind.split('#').last + '/' + @attributes.occi!.core!.id
65
59
  end
66
60
 
67
- def check
68
- definitions = OCCI::Model.get_by_id(self.kind).attributes if self.kind
69
- self.mixins.each do |mixin_id|
70
- mixin = OCCI::Model.get_by_id(mixin_id)
61
+ # check attributes against their definitions and set defaults
62
+ # @param [OCCI::Model] model representation of the OCCI model to check the attributes against
63
+ def check(model)
64
+ raise "No kind defined" unless @kind
65
+ definitions = model.get_by_id(@kind).attributes
66
+ @mixins.each do |mixin_id|
67
+ mixin = model.get_by_id(mixin_id)
71
68
  next if mixin.nil?
72
69
  definitions.merge!(mixin.attributes) if mixin.attributes
73
- end if self.mixins
70
+ end if @mixins
74
71
 
75
- self.attributes = Entity.check(self.attributes, definitions) if definitions
72
+ @attributes = Entity.check(@attributes, definitions) if definitions
76
73
  end
77
74
 
75
+ # @param [OCCI::Core::Attributes] attributes
76
+ # @param [OCCI::Core::AttributeProperties] definitions
77
+ # @return [OCCI::Core::Attributes] attributes with their defaults set
78
78
  def self.check(attributes, definitions)
79
79
  attributes = OCCI::Core::Attributes.new(attributes)
80
80
  definitions.each_key do |key|
81
81
  properties = definitions[key]
82
- value = attributes[key] ||= properties[:default]
82
+ value = attributes[key] ||= properties[:default]
83
83
  if properties.include?(:type)
84
84
  raise "required attribute #{key} not found" if value.nil? && properties.required
85
85
  next if value.nil? && !properties.required
86
86
  case properties.type
87
- when 'string'
88
- raise "attribute #{key} with value #{value} from class #{value.class.name} does not match attribute property type #{properties.type}" unless value.kind_of?(String)
89
- raise "attribute #{key} with length #{value.length} not in range #{properties.minimum}-#{properties.maximum}" unless (properties.minimum..properties.maximum) === value.length if properties.minimum && properties.maximum
90
87
  when 'number'
91
88
  raise "attribute #{key} value #{value} from class #{value.class.name} does not match attribute property type #{properties.type}" unless value.kind_of?(Numeric)
92
89
  raise "attribute #{key} with value #{value} not in range #{properties.minimum}-#{properties.maximum}" unless (properties.minimum..properties.maximum) === value if properties.minimum && properties.maximum
93
90
  when 'boolean'
94
91
  raise "attribute #{key} value #{value} from class #{value.class.name} does not match attribute property type #{properties.type}" unless !!value == value
92
+ else
93
+ raise "attribute #{key} with value #{value} from class #{value.class.name} does not match attribute property type #{properties.type}" unless value.kind_of?(String)
94
+ raise "attribute #{key} with length #{value.length} not in range #{properties.minimum}-#{properties.maximum}" unless (properties.minimum..properties.maximum) === value.length if properties.minimum && properties.maximum
95
95
  end
96
96
  raise "attribute #{key} with value #{value} does not match pattern #{properties.pattern}" if value.to_s.scan(Regexp.new(properties.pattern)).empty? if properties.pattern
97
97
  attributes[key] = value
@@ -99,23 +99,18 @@ module OCCI
99
99
  attributes[key] = check(value, definitions[key])
100
100
  end
101
101
  end
102
- attributes.delete_if { |k, v| v.nil? } # remove empty attributes
102
+ attributes.delete_if { |_, v| v.nil? } # remove empty attributes
103
103
  return attributes
104
104
  end
105
105
 
106
- def convert_value(val, duping=false) #:nodoc:
107
- case val
108
- when self.class
109
- val.dup
110
- when ::Hash
111
- val = val.dup if duping
112
- self.class.subkey_class.new.merge(val) unless val.kind_of?(Hashie::Mash)
113
- val
114
- when Array
115
- val.collect { |e| convert_value(e) }
116
- else
117
- val
118
- end
106
+ # @param [Hash] options
107
+ # @return [Hashie::Mash] entity as Hashie::Mash to be parsed into a JSON object
108
+ def as_json(options={ })
109
+ entity = Hashie::Mash.new
110
+ entity.kind = @kind if @kind
111
+ entity.mixins = @mixins if @mixins.any?
112
+ entity.attributes = @attributes if @attributes.any?
113
+ entity
119
114
  end
120
115
 
121
116
  end