occi 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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