occi-core 4.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +43 -0
  5. data/.yardopts +1 -0
  6. data/AUTHORS +9 -0
  7. data/Gemfile +11 -0
  8. data/LICENSE +13 -0
  9. data/README.md +212 -0
  10. data/Rakefile +28 -0
  11. data/config/occi.yml +4 -0
  12. data/ext/mkrf_conf.rb +35 -0
  13. data/lib/occi/collection.rb +192 -0
  14. data/lib/occi/core/action.rb +32 -0
  15. data/lib/occi/core/action_instance.rb +38 -0
  16. data/lib/occi/core/actions.rb +20 -0
  17. data/lib/occi/core/attribute.rb +99 -0
  18. data/lib/occi/core/attributes.rb +172 -0
  19. data/lib/occi/core/categories.rb +51 -0
  20. data/lib/occi/core/category.rb +153 -0
  21. data/lib/occi/core/entities.rb +47 -0
  22. data/lib/occi/core/entity.rb +264 -0
  23. data/lib/occi/core/kind.rb +58 -0
  24. data/lib/occi/core/kinds.rb +22 -0
  25. data/lib/occi/core/link.rb +95 -0
  26. data/lib/occi/core/links.rb +34 -0
  27. data/lib/occi/core/mixin.rb +55 -0
  28. data/lib/occi/core/mixins.rb +41 -0
  29. data/lib/occi/core/properties.rb +35 -0
  30. data/lib/occi/core/related.rb +7 -0
  31. data/lib/occi/core/resource.rb +78 -0
  32. data/lib/occi/core/resources.rb +14 -0
  33. data/lib/occi/core.rb +31 -0
  34. data/lib/occi/helpers/inspect.rb +12 -0
  35. data/lib/occi/infrastructure/compute.rb +122 -0
  36. data/lib/occi/infrastructure/network/ipnetwork.rb +27 -0
  37. data/lib/occi/infrastructure/network.rb +107 -0
  38. data/lib/occi/infrastructure/networkinterface/ipnetworkinterface.rb +27 -0
  39. data/lib/occi/infrastructure/networkinterface.rb +103 -0
  40. data/lib/occi/infrastructure/os_tpl.rb +19 -0
  41. data/lib/occi/infrastructure/resource_tpl.rb +19 -0
  42. data/lib/occi/infrastructure/storage.rb +61 -0
  43. data/lib/occi/infrastructure/storagelink.rb +56 -0
  44. data/lib/occi/infrastructure.rb +25 -0
  45. data/lib/occi/log.rb +66 -0
  46. data/lib/occi/model.rb +86 -0
  47. data/lib/occi/parser/json.rb +34 -0
  48. data/lib/occi/parser/ova.rb +35 -0
  49. data/lib/occi/parser/ovf.rb +154 -0
  50. data/lib/occi/parser/text.rb +234 -0
  51. data/lib/occi/parser/xml.rb +18 -0
  52. data/lib/occi/parser.rb +78 -0
  53. data/lib/occi/settings.rb +9 -0
  54. data/lib/occi/version.rb +3 -0
  55. data/lib/occi-core.rb +50 -0
  56. data/occi-core.gemspec +36 -0
  57. data/spec/occi/collection_spec.rb +38 -0
  58. data/spec/occi/core/attribute_spec.rb +0 -0
  59. data/spec/occi/core/attributes_spec.rb +42 -0
  60. data/spec/occi/core/categories_spec.rb +27 -0
  61. data/spec/occi/core/category_spec.rb +38 -0
  62. data/spec/occi/core/entity_spec.rb +46 -0
  63. data/spec/occi/core/resource_spec.rb +18 -0
  64. data/spec/occi/infrastructure/compute_spec.rb +29 -0
  65. data/spec/occi/log_spec.rb +14 -0
  66. data/spec/occi/model_spec.rb +50 -0
  67. data/spec/occi/parser/text_spec.rb +31 -0
  68. data/spec/occi/parser_spec.rb +114 -0
  69. data/spec/occi/test.json +33 -0
  70. data/spec/occi/test.ova +0 -0
  71. data/spec/occi/test.ovf +198 -0
  72. data/spec/spec_helper.rb +25 -0
  73. metadata +304 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ebef6c43e395ded42db83bb1f066f3d2513f4f8a
4
+ data.tar.gz: 2d16d544304fac4f15bf90fa8d69a6785c2ffeb0
5
+ SHA512:
6
+ metadata.gz: 340f7fbb10f0cf02b07c9c6f4833ed1b4c1733ce8cd54cf9f23e938f44b1401009828b8800f1dfcd85cd5e42a1984a0d345d04ee8434c7acbbe61d6a18302861
7
+ data.tar.gz: dae77c9cc1033df83ede5d42405ddbfa02baef2f56288927c83963c59471174591bc5b04258eccf537383a24db62bffa5cb944ca58db89e6c2aa65fce3090cfe
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ *.gem
2
+ *.swp
3
+ .project
4
+ .idea
5
+ .yardoc
6
+ .bundle
7
+ .rvmrc
8
+ lib/occiantlr/output/
9
+ pkg
10
+ tmp
11
+ log
12
+ coverage
13
+ vendor
14
+ collection
15
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper --color --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,43 @@
1
+ language: ruby
2
+
3
+ before_install:
4
+ - sudo apt-get install -qq libonig-dev
5
+
6
+ rvm:
7
+ - 1.8.7
8
+ - 1.9.3
9
+ - 2.0.0
10
+ - ruby-head
11
+ - jruby-19mode
12
+ - jruby-head
13
+
14
+ jdk:
15
+ - openjdk7
16
+ - oraclejdk7
17
+ - openjdk6
18
+
19
+ matrix:
20
+ allow_failures:
21
+ - rvm: ruby-head
22
+ - rvm: jruby-head
23
+ exclude:
24
+ - rvm: 1.8.7
25
+ jdk: openjdk7
26
+ - rvm: 1.8.7
27
+ jdk: oraclejdk7
28
+ - rvm: 1.9.3
29
+ jdk: openjdk7
30
+ - rvm: 1.9.3
31
+ jdk: oraclejdk7
32
+ - rvm: 2.0.0
33
+ jdk: openjdk7
34
+ - rvm: 2.0.0
35
+ jdk: oraclejdk7
36
+ - rvm: ruby-head
37
+ jdk: openjdk7
38
+ - rvm: ruby-head
39
+ jdk: oraclejdk7
40
+
41
+ branches:
42
+ only:
43
+ - master
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --title "Documentation of the OCCI gem" --markup markdown --private
data/AUTHORS ADDED
@@ -0,0 +1,9 @@
1
+ rOcci was designed and is mainly developed by Florian Feldhaus (GWDG) and Piotr Kasprzak (GWDG) in Germany.
2
+
3
+ Special thanks to the following extraordinary individuals, whithout whom rOcci would not be possible:
4
+
5
+ * Hayati Bice - who wrote the initial version of an Occi server rOcci is based on
6
+ * Max Günther - who wrote the EC2 backend
7
+ * Andre Thevapalan - for his input regarding the JSON rendering
8
+ * Boris Parak - especially for his input regarding the Client / Client DSL and CLI
9
+ * the OCCI Working Group - for developing OCCI
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org/"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rubygems-tasks', :git => 'git://github.com/postmodern/rubygems-tasks.git'
7
+ end
8
+
9
+ platforms :ruby_18 do
10
+ gem 'oniguruma'
11
+ end
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012 GWDG
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,212 @@
1
+ rOCCI-core - A Ruby OCCI Framework
2
+ =================================
3
+
4
+ [![Build Status](https://secure.travis-ci.org/gwdg/rOCCI-core.png)](http://travis-ci.org/gwdg/rOCCI-core)
5
+ [![Dependency Status](https://gemnasium.com/gwdg/rOCCI-core.png)](https://gemnasium.com/gwdg/rOCCI-core)
6
+ [![Gem Version](https://fury-badge.herokuapp.com/rb/occi-core.png)](https://badge.fury.io/rb/occi-core)
7
+ [![Code Climate](https://codeclimate.com/github/gwdg/rOCCI-core.png)](https://codeclimate.com/github/gwdg/rOCCI-core)
8
+
9
+ Requirements
10
+ ------------
11
+
12
+ Ruby
13
+ * at least version 1.8.7 is required
14
+
15
+ The following setup is recommended
16
+
17
+ * usage of the Ruby Version Manager
18
+ * Ruby 1.9.3
19
+ * RubyGems installed
20
+
21
+ The following libraries / packages may be required to use rOCCI
22
+
23
+ * libxslt-dev
24
+ * libxml2-dev
25
+ * **only if using Ruby 1.8.7:** libonig-dev (Linux) or oniguruma (Mac)
26
+
27
+ Installation
28
+ ------------
29
+
30
+ **[Mac OS X has some special requirements for the installation. Detailed information can be found in
31
+ doc/macosx.md.](doc/macosx.md)**
32
+
33
+ To install the most recent stable version
34
+
35
+ gem install occi-core
36
+
37
+ To install the most recent beta version
38
+
39
+ gem install occi-core --pre
40
+
41
+ ### Installation from source
42
+
43
+ To use rOCCI from source it is very much recommended to use RVM. [Install RVM](https://rvm.io/rvm/install/) with
44
+
45
+ curl -L https://get.rvm.io | bash -s stable --ruby
46
+
47
+ #### Ruby
48
+
49
+ To build and install the bleeding edge version from master
50
+
51
+ git clone git://github.com/gwdg/rOCCI-core.git
52
+ cd rOCCI-core
53
+ rvm install ruby-1.9.3
54
+ rvm --create --ruby-version use 1.9.3@rOCCI-core
55
+ bundle install
56
+ rake test
57
+
58
+ Usage
59
+ -----
60
+ #### Logging
61
+
62
+ The OCCI gem includes its own logging mechanism using a message queue. By default, no one is listening to that queue.
63
+ A new OCCI Logger can be initialized by specifying the log destination (either a filename or an IO object like
64
+ STDOUT) and the log level.
65
+
66
+ Occi::Log.new(STDOUT,Occi::Log::INFO)
67
+
68
+ You can create multiple Loggers to receive the log output.
69
+
70
+ You can always, even if there is no logger defined, log output using the class methods of OCCI::Log e.g.
71
+
72
+ Occi::Log.info("Test message")
73
+
74
+ #### Registering categories in the OCCI Model
75
+
76
+ Before the parser may be used, the available categories have to be registered in the OCCI Model.
77
+
78
+ For categories already specified by the OCCI WG a method exists in the OCCI Model class to register them:
79
+
80
+ model = Occi::Model.new
81
+ model.register_infrastructure
82
+
83
+ Further categories can either be registered from files which include OCCI collections in JSON formator or from parsed
84
+ JSON objects (e.g. from the query interface of an OCCI service endpoint).
85
+
86
+ #### Parsing OCCI messages
87
+
88
+ The OCCI gem includes a Parser to easily parse OCCI messages. With a given media type (e.g. json,
89
+ xml or plain text) the parser analyses the content of the message body and, if supplied,
90
+ the message header. As the text/plain and text/occi media type do not clearly distinguish between a message with a
91
+ category and a message with an entity which has a kind, it has to be specified if the message contains a category (e
92
+ .g. for user defined mixins)
93
+
94
+ OCCI messages can be parsed to an OCCI collection for example like
95
+
96
+ media_type = 'text/plain'
97
+ body = %Q|Category: compute; scheme="http://schemas.ogf.org/occi/infrastructure#"; class="kind"|
98
+ collection=Occi::Parser.parse(media_type, body)
99
+
100
+ #### Parsing OVF / OVA files
101
+
102
+ Parsing of OVF/OVA files is partly supported and will be improved in future versions.
103
+
104
+ The example in [DMTF DSP 2021](http://www.dmtf.org/sites/default/files/standards/documents/DSP2021_1.0.0.tar) is
105
+ bundled with rOCCI and can be parsed to an OCCI collection with
106
+
107
+ require 'open-uri'
108
+ ova=open 'https://raw.github.com/gwdg/rOCCI/master/spec/occi/test.ova'
109
+ collection=Occi::Parser.ova(ova.read)
110
+
111
+ Currently only the following entries of OVF files are parsed
112
+
113
+ * File in References
114
+ * Disk in the DiskSection
115
+ * Network in the NetworkSection
116
+ * In the VirutalSystemSection:
117
+ ** Info
118
+ ** in the VirtualHardwareSection the items regarding
119
+ *** Processor
120
+ *** Memory
121
+ *** Ethernet Adapter
122
+ *** Parallel port
123
+
124
+ ### Using the OCCI model
125
+
126
+ The occi-core gem includes all OCCI Core classes necessary to handly arbitrary OCCI objects.
127
+
128
+ Changelog
129
+ ---------
130
+
131
+ ### Version 3.1
132
+ * added basic OS Keystone support
133
+ * added support for PKCS12 credentials for X.509 authN
134
+ * updated templates for plain output formatting
135
+ * minor client API changes
136
+ * several bugfixes
137
+
138
+ ### Version 3.0
139
+
140
+ * many bugfixes
141
+ * rewrote Core classes to use metaprogramming techniques
142
+ * added VCR cassettes for reliable testing against prerecorded server responses
143
+ * several updates to the OCCI Client
144
+ * started work on an OCCI Client using AMQP as transport protocol
145
+ * added support for keystone authentication to be used with the OpenStack OCCI server
146
+ * updated dependencies
147
+ * updated rspec tests
148
+ * started work on cucumber features
149
+
150
+ ### Version 2.5
151
+
152
+ * improved OCCI Client
153
+ * improved documentation
154
+ * several bugfixes
155
+
156
+ ### Version 2.4
157
+
158
+ * Changed OCCI attribute properties from lowercase to first letter uppercase (e.g. type -> Type, default -> Default, ...)
159
+
160
+ ### Version 2.3
161
+
162
+ * OCCI objects are now initialized with a list of attributes instead of a hash. Thus it is easier to check which
163
+ attributes are expected by a class and helps prevent errors.
164
+ * Parsing of a subset of the OVF specification is supported. Further parts of the specification will be covered in
165
+ future versions of rOCCI.
166
+
167
+ ### Version 2.2
168
+
169
+ * OCCI Client added. The client simplifies the execution of OCCI commands and provides shortcuts for often used steps.
170
+
171
+ ### Version 2.1
172
+
173
+ * Several improvements to the gem structure and code documentation. First rSpec test were added. Readme has been extended to include instructions how the gem can be used.
174
+
175
+ ### Version 2.0
176
+
177
+ * Starting with version 2.0 Florian Feldhaus and Piotr Kasprzak took over the development of the OCCI gem. The codebase was taken from the rOCCI framework and improved to be bundled as a standalone gem.
178
+
179
+ ### Version 1.X
180
+
181
+ * Version 1.X of the OCCI gem has been developed by retr0h and served as a simple way to access the first OpenNebula OCCI implementation.
182
+
183
+ Development
184
+ -----------
185
+
186
+ Checkout latest version from git:
187
+
188
+ git clone git://github.com/gwdg/rOCCI-core.git
189
+
190
+ Change to rOCCI-core folder
191
+
192
+ cd rOCCI-core
193
+
194
+ Install dependencies
195
+
196
+ bundle install
197
+
198
+ ### Code Documentation
199
+
200
+ [Code Documentation for rOCCI by YARD](http://rubydoc.info/github/gwdg/rOCCI-core/)
201
+
202
+ ### Continuous integration
203
+
204
+ [Continuous integration for rOCCI by Travis-CI](http://travis-ci.org/gwdg/rOCCI-core/)
205
+
206
+ ### Contribute
207
+
208
+ 1. Fork it.
209
+ 2. Create a branch (git checkout -b my_markup)
210
+ 3. Commit your changes (git commit -am "My changes")
211
+ 4. Push to the branch (git push origin my_markup)
212
+ 5. Create an Issue with a link to your branch
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'rubygems/tasks'
3
+
4
+ task :default => 'test'
5
+
6
+ desc "Run all tests; includes rspec and coverage reports"
7
+ task :test => 'rcov:all'
8
+
9
+ Gem::Tasks.new(:build => {:tar => true, :zip => true}, :sign => {:checksum => true, :pgp => false})
10
+
11
+ namespace :rcov do
12
+ require 'rspec/core/rake_task'
13
+
14
+ RSpec::Core::RakeTask.new(:rspec) do |t|
15
+ ENV['COVERAGE'] = "true"
16
+ end
17
+
18
+ desc "Run rspec to generate aggregated coverage"
19
+ task :all do |t|
20
+ rm "coverage/coverage.data" if File.exist?("coverage/coverage.data")
21
+ Rake::Task['rcov:rspec'].invoke
22
+ end
23
+ end
24
+
25
+ require 'yard'
26
+ YARD::Rake::YardocTask.new(:yard) do |t|
27
+ t.options = ['--any', '--extra', '--opts'] # optional
28
+ end
data/config/occi.yml ADDED
@@ -0,0 +1,4 @@
1
+ # config/occi.yml
2
+ core: &core
3
+ compatibility: true
4
+ verify_attribute_pattern: false
data/ext/mkrf_conf.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'rubygems/command.rb'
3
+ require 'rubygems/dependency_installer.rb'
4
+
5
+ begin
6
+ Gem::Command.build_args = ARGV
7
+ rescue NoMethodError
8
+ # do nothing but warn the user
9
+ warn "Gem::Command doesn't have a method named 'build_args'!"
10
+ end
11
+
12
+ warn 'Installing platform-specific dependencies.'
13
+
14
+ warn 'Installing the most recent version of \'rake\''
15
+ inst = Gem::DependencyInstaller.new
16
+ inst.install "rake"
17
+
18
+ if RUBY_PLATFORM == "java"
19
+ # Nothing to install for rOCCI-core
20
+ #warn 'Installing dependencies specific for jRuby'
21
+ else
22
+ warn 'Installing dependencies specific for Ruby'
23
+
24
+ rver = RUBY_VERSION.split('.').map{ |elm| elm.to_i }
25
+ if rver[0] == 1 && rver[1] < 9
26
+ warn 'Installing \'oniguruma\' for Ruby 1.8.x'
27
+ warn 'Make sure you have \'libonig-dev\' installed!'
28
+ inst.install "oniguruma"
29
+ end
30
+ end
31
+
32
+ # create dummy rakefile to indicate success
33
+ f = File.open(File.join(File.dirname(__FILE__), "Rakefile"), "w")
34
+ f.write "task :default\n"
35
+ f.close
@@ -0,0 +1,192 @@
1
+ module Occi
2
+ class Collection
3
+
4
+ include Occi::Helpers::Inspect
5
+
6
+ attr_accessor :kinds, :mixins, :actions, :resources, :links, :action, :model
7
+
8
+ # Initialize a new OCCI Collection by initializing all supplied OCCI objects
9
+ #
10
+ # @param [Hash] collection including one or more of the keys kinds, mixins, actions, resources, links
11
+ def initialize(collection={}, model = Occi::Model.new)
12
+ collection = Hashie::Mash.new(collection) unless collection.kind_of? Occi::Collection
13
+
14
+ @kinds = Occi::Core::Kinds.new
15
+ @mixins = Occi::Core::Mixins.new
16
+ @actions = Occi::Core::Actions.new
17
+ @resources = Occi::Core::Resources.new
18
+ @links = Occi::Core::Links.new
19
+
20
+ self.model = model if model
21
+
22
+ @kinds.merge collection.kinds.to_a.collect { |kind| Occi::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) }
23
+ @mixins.merge collection.mixins.to_a.collect { |mixin| Occi::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) }
24
+ @actions.merge collection.actions.to_a.collect { |action| Occi::Core::Action.new(action.scheme, action.term, action.title, action.attributes) }
25
+ @resources.merge collection.resources.to_a.collect { |resource| Occi::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.links) }
26
+ @links.merge collection.links.to_a.collect { |link| Occi::Core::Link.new(link.kind, link.mixins, link.attributes) }
27
+ @action = Occi::Core::ActionInstance.new(collection.action, collection.attributes) if collection.action
28
+ end
29
+
30
+ def <<(object)
31
+ object.kind_of? Occi::Core::Kind and self.kinds << object
32
+ object.kind_of? Occi::Core::Mixin and self.mixins << object
33
+ object.kind_of? Occi::Core::Action and self.actions << object
34
+ object.kind_of? Occi::Core::Resource and self.resources << object
35
+ object.kind_of? Occi::Core::Link and self.links << object
36
+ end
37
+
38
+ def ==(category)
39
+ not intersect(category).empty?
40
+ end
41
+
42
+ # @return [Occi::Core::Categories] categories combined list of all kinds, mixins and actions
43
+ def categories
44
+ Occi::Core::Categories.new(@kinds + @mixins + @actions)
45
+ end
46
+
47
+ # @return [Occi::Core::Entities] entities combined list of all resources and links
48
+ def entities
49
+ Occi::Core::Entities.new(@resources + @links)
50
+ end
51
+
52
+ # @param [Occi::Core::Model] model
53
+ # @return [Occi::Core::Model]
54
+ def model=(model)
55
+ @model = model
56
+ @kinds.model = model
57
+ @mixins.model = model
58
+ @actions.model = model
59
+ @resources.model = model
60
+ @links.model = model
61
+ end
62
+
63
+ def check
64
+ @resources.check
65
+ @links.check
66
+ # TODO: check action instance format, should check be applicable?
67
+ #@action.check
68
+ end
69
+
70
+ # @param [Occi::Collection] other_collection
71
+ # @return [Occi::Collection]
72
+ def merge!(other_collection)
73
+ merge other_collection, self
74
+ end
75
+
76
+ # @param [Occi::Collection] other_collection
77
+ # @param [Occi::Collection] collection
78
+ # @return [Occi::Collection]
79
+ def merge(other_collection, collection=self.clone)
80
+ collection.kinds.merge other_collection.kinds.select { |kind| get_by_id(kind.type_identifier).nil? }
81
+ collection.mixins.merge other_collection.mixins.select { |mixin| get_by_id(mixin.type_identifier).nil? }
82
+ collection.actions.merge other_collection.actions.select { |action| get_by_id(action.type_identifier).nil? }
83
+ collection.resources.merge other_collection.resources.select { |resource| get_by_id(resource.id).nil? }
84
+ collection.links.merge other_collection.links.select { |link| get_by_id(link.type_identifier).nil? }
85
+ collection.action = other_collection.action if other_collection.action
86
+ collection
87
+ end
88
+
89
+ # @param [Occi::Collection] other_collection
90
+ # @return [Occi::Collection]
91
+ def intersect!(other_collection)
92
+ intersect other_collection, self
93
+ end
94
+
95
+ # @param [Occi::Collection] other_collection
96
+ # @param [Occi::Collection] collection
97
+ # @return [Occi::Collection]
98
+ def intersect(other_collection, collection=self.clone)
99
+ collection.kinds.replace other_collection.kinds.select { |kind| get_by_id(kind.type_identifier) }
100
+ collection.mixins.replace other_collection.mixins.select { |mixin| get_by_id(mixin.type_identifier) }
101
+ collection.actions.replace other_collection.actions.select { |action| get_by_id(action.type_identifier) }
102
+ collection.resources.replace other_collection.resources.select { |resource| get_by_id(resource.id) }
103
+ collection.links.replace other_collection.links.select { |link| get_by_id(link.type_identifier) }
104
+ if collection.action == other_collection.action
105
+ collection.action = other_collection.action
106
+ else
107
+ collection.action = nil
108
+ end
109
+ collection
110
+ end
111
+
112
+ # Returns the category corresponding to a given id
113
+ #
114
+ # @param [String] id
115
+ # @return [Occi::Core::Category]
116
+ def get_by_id(id)
117
+ object = self.categories.select { |category| category.type_identifier == id }
118
+ object = self.entities.select { |entity| entity.id == id } if object.empty?
119
+ object.first
120
+ end
121
+
122
+ # Returns the category corresponding to a given location
123
+ #
124
+ # @param [URI] location
125
+ # @return [Occi::Core::Category]
126
+ def get_by_location(location)
127
+ self.categories.select { |category| category.location == location }.first
128
+ end
129
+
130
+ # @return [true,false] true if collection is empty, false otherwise
131
+ def empty?
132
+ @kinds.empty? && @mixins.empty? && @actions.empty? && @resources.empty? && @links.empty? && @action.nil?
133
+ end
134
+
135
+ # Returns a collection with all categories related to the specified category
136
+ #
137
+ # @param [Occi::Core::Category] category
138
+ # @return [Occi::Core::Collection]
139
+ def get_related_to(category)
140
+ collection = self.class.new
141
+ collection.kinds = @kinds.get_related_to(category)
142
+ collection.mixins = @mixins.get_related_to(category)
143
+ collection
144
+ end
145
+
146
+ # @return [Hashie::Mash] json representation
147
+ def as_json(options = {})
148
+ collection = Hashie::Mash.new
149
+ collection.kinds = @kinds.collect { |kind| kind.as_json } if @kinds.any?
150
+ collection.mixins = @mixins.collect { |mixin| mixin.as_json } if @mixins.any?
151
+ collection.actions = @actions.collect { |action_category| action_category.as_json } if @actions.any?
152
+ collection.resources = @resources.collect { |resource| resource.as_json } if @resources.any?
153
+ # if there is only one resource and the links inside the resource have no location,
154
+ # then these links must be rendered as separate links inside the collection
155
+ if !collection.resources.nil? && collection.resources.size == 1
156
+ if collection.resources.first.links.blank? && @links.empty?
157
+ lnks = @resources.first.links
158
+ else
159
+ lnks = @links
160
+ end
161
+ else
162
+ lnks = @links
163
+ end
164
+ collection.links = lnks.collect { |link| link.as_json } if lnks.to_a.any?
165
+ collection.action = @action.as_json if @action
166
+ collection
167
+ end
168
+
169
+ # @return [String] text representation
170
+ def to_text
171
+ text = ""
172
+ text << self.categories.collect { |category| category.to_text }.join("\n")
173
+ text << "\n" if self.categories.any?
174
+ raise "Only one resource allowed for rendering to text/plain" if self.resources.size > 1
175
+ text << self.resources.collect { |resource| resource.to_text }.join("\n")
176
+ text << self.links.collect { |link| link.to_text_link }.join("\n")
177
+ text << self.action.to_text if self.action
178
+ text
179
+ end
180
+
181
+ def to_header
182
+ header = Hashie::Mash.new
183
+ header['Category'] = self.categories.collect { |category| category.to_string_short }.join(',') if self.categories.any?
184
+ raise "Only one resource allowed for rendering to text/occi" if self.resources.size > 1
185
+ header = self.resources.first.to_header if self.resources.any?
186
+ header['Link'] = self.links.collect { |link| link.to_string }.join(',') if self.links.any?
187
+ header = self.action.to_header if self.action
188
+ header
189
+ end
190
+
191
+ end
192
+ end
@@ -0,0 +1,32 @@
1
+ module Occi
2
+ module Core
3
+ class Action < Occi::Core::Category
4
+
5
+ # @param [String ] scheme
6
+ # @param [String] term
7
+ # @param [String] title
8
+ # @param [Hash] attributes
9
+ def initialize(scheme='http://schemas.ogf.org/occi/core#',
10
+ term='action',
11
+ title=nil,
12
+ attributes=Occi::Core::Attributes.new)
13
+ super scheme, term, title, attributes
14
+ end
15
+
16
+ # @return [String] text representation
17
+ def to_text
18
+ text = super
19
+ text << ';attributes=' + @attributes.names.join(' ').inspect if @attributes.any?
20
+ text
21
+ end
22
+
23
+ # @return [Hash] hash containing the HTTP headers of the text/occi rendering
24
+ def to_header
25
+ header = super
26
+ header["Category"] << ';attributes=' + @attributes.names.join(' ').inspect if @attributes.any?
27
+ header
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ module Occi
2
+ module Core
3
+ class ActionInstance
4
+
5
+ include Occi::Helpers::Inspect
6
+
7
+ attr_accessor :action, :attributes, :model
8
+
9
+ class_attribute :action, :attributes
10
+
11
+ self.attributes = Occi::Core::Attributes.new
12
+
13
+ self.action = Occi::Core::Action.new scheme='http://schemas.ogf.org/occi/core#',
14
+ term='action_instance',
15
+ title='action',
16
+ attributes=self.attributes
17
+
18
+ def initialize(action = self.action, attributes=self.attributes)
19
+ if action.kind_of? String
20
+ scheme, term = action.split '#'
21
+ action = Occi::Core::Action.new(scheme, term)
22
+ end
23
+ @action = action
24
+ @attributes = attributes.convert
25
+ end
26
+
27
+ # @param [Hash] options
28
+ # @return [Hashie::Mash] json representation
29
+ def as_json(options={})
30
+ action = Hashie::Mash.new
31
+ action.action = @action.to_s if @action
32
+ action.attributes = @attributes if @attributes.any?
33
+ action
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ module Occi
2
+ module Core
3
+ class Actions < Occi::Core::Categories
4
+
5
+ private
6
+
7
+ def convert(category)
8
+ category = super category
9
+
10
+ if category.kind_of? String
11
+ scheme, term = category.split '#'
12
+ scheme += '#'
13
+ category = Occi::Core::Action.new(scheme, term)
14
+ end
15
+ category
16
+ end
17
+
18
+ end
19
+ end
20
+ end