Skip to content

Commit

Permalink
Filtering categories in collections
Browse files Browse the repository at this point in the history
- added method to get all categories related to a given category from a collection
- improved get method in model to use new filtering method of collection
- added and updated methods in client to allow retrieval of all entity, resource and link types and type identifiers
- added and updated rspec tests for collection and model
  • Loading branch information
ffeldhaus committed Jan 2, 2013
1 parent 7d4b861 commit 4134458
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 51 deletions.
94 changes: 79 additions & 15 deletions lib/occi/api/client/client_http.rb
Expand Up @@ -142,6 +142,45 @@ def get_resource(resource_type)

end

# Retrieves all entity type identifiers related to a given type identifier
#
# @example
# client.get_entity_type_identifiers_related_to 'network'
# # => [ "http://schemas.ogf.org/occi/infrastructure#network",
# # "http://schemas.ogf.org/occi/infrastructure#ipnetwork" ]
#
# @param [String] type_identifier
# @return [Array<String>] list of available entity type identifiers related to given type identifier in a human-readable format
def get_entity_types_related_to(type_identifier)
Occi::Log.debug("Getting entity type identifiers related to #{type_identifier}")
collection = @model.get type_identifier
collection.kinds.collect { |kind| kind.type_identifier }
end

# Retrieves all available entity types.
#
# @example
# client.get_entity_types # => [ "compute", "storage", "network" ]
#
# @return [Array<String>] list of available entity types in a human-readable format
def get_entity_types
Occi::Log.debug("Getting entity types ...")
@model.kinds.collect { |kind| kind.term }
end

# Retrieves all available entity type identifiers.
#
# @example
# client.get_entity_type_identifiers
# # => [ "http://schemas.ogf.org/occi/infrastructure#compute",
# # "http://schemas.ogf.org/occi/infrastructure#storage",
# # "http://schemas.ogf.org/occi/infrastructure#network" ]
#
# @return [Array<String>] list of available entity types in a OCCI ID format
def get_entity_type_identifiers
get_entity_types_related_to Occi::Core::Entity.kind.type_identifier
end

# Retrieves all available resource types.
#
# @example
Expand All @@ -150,25 +189,50 @@ def get_resource(resource_type)
# @return [Array<String>] list of available resource types in a human-readable format
def get_resource_types
Occi::Log.debug("Getting resource types ...")
@model.kinds.collect { |kind| kind.term }
collection = @model.get Occi::Core::Resource.kind
collection.kinds.collect { |kind| kind.term }
end

# Retrieves all available resource type identifiers.
#
# @example
# client.get_resource_type_identifiers
# client.get_resource_type_identifiers
# # => [ "http://schemas.ogf.org/occi/infrastructure#compute",
# # "http://schemas.ogf.org/occi/infrastructure#storage",
# # "http://schemas.ogf.org/occi/infrastructure#network" ]
#
# @return [Array<String>] list of available resource types in a Occi ID format
def get_resource_type_identifiers
Occi::Log.debug("Getting resource identifiers ...")
@model.kinds.collect { |kind| kind.type_identifier }
get_entity_types_related_to Occi::Core::Resource.kind.type_identifier

end

# Retrieves all available link types.
#
# @example
# client.get_link_types # => [ "storagelink", "networkinterface" ]
#
# @return [Array<String>] list of available link types in a human-readable format
def get_link_types
Occi::Log.debug("Getting link types ...")
collection = @model.get Occi::Core::Link.kind
collection.kinds.collect { |kind| kind.term }
end

# Retrieves all available link type identifiers.
#
# @example
# client.get_link_type_identifiers
# # => [ "http://schemas.ogf.org/occi/infrastructure#storagelink",
# # "http://schemas.ogf.org/occi/infrastructure#networkinterface" ]
#
# @return [Array<String>] list of available link types in a OCCI ID format
def get_link_type_identifiers
get_entity_types_related_to Occi::Core::Link.kind.type_identifier
end

# Looks up a mixin using its name and, optionally, a type as well.
# Will return mixin's full location (a link) or a description.
# Will return mixin's full location (a link) or a description.
#
# @example
# client.find_mixin "debian6"
Expand Down Expand Up @@ -286,7 +350,7 @@ def get_mixin_types
# @example
# client.get_mixin_type_identifiers
# # => ['http://schemas.ogf.org/occi/infrastructure#os_tpl',
# # 'http://schemas.ogf.org/occi/infrastructure#resource_tpl']
# # 'http://schemas.ogf.org/occi/infrastructure#resource_tpl']
#
# @return [Array<String>] list of available mixin type identifiers
def get_mixin_type_identifiers
Expand Down Expand Up @@ -345,7 +409,7 @@ def list(resource_type_identifier=nil)
# Retrieves descriptions for available resources specified by a type
# identifier or resource location. If no type identifier or location
# is specified, all available resources in all available resource types
# will be described.
# will be described.
#
# @example
# client.describe
Expand Down Expand Up @@ -397,7 +461,7 @@ def describe(resource_type_identifier=nil)

# Creates a new resource on the server. Resource must be provided
# as an instance of Occi::Core::Entity, e.g. instantiated using
# the get_resource method.
# the get_resource method.
#
# @example
# res = client.get_resource "compute"
Expand Down Expand Up @@ -477,7 +541,7 @@ def deploy(location)
# @example
# client.delete "compute" # => true
# client.delete "http://schemas.ogf.org/occi/infrastructure#compute" # => true
# client.delete "http://localhost:3300/compute/245j42594...98s9df8s9f" # => true
# client.delete "http://localhost:3300/compute/245j42594...98s9df8s9f" # => true
#
# @param [String] resource type identifier, type name or location
# @return [Boolean] status
Expand Down Expand Up @@ -552,7 +616,7 @@ def set_logger(log_options)
end

# Sets auth method and appropriate httparty attributes. Supported auth methods
# are: ["basic", "digest", "x509", "none"]
# are: ["basic", "digest", "x509", "none"]
#
# @example
# change_auth { :type => "none" }
Expand Down Expand Up @@ -601,7 +665,7 @@ def change_auth(auth_options)
# certs_to_file_ary "~/.globus/usercert.pem"
# # => [#<String>, #<String>, ...]
#
# @param [String] Path to a PEM file containing certificates
# @param [String] Path to a PEM file containing certificates
# @return [Array<String>] An array of read certificates
def certs_to_file_ary(ca_file)
# TODO: read and separate multiple certificates
Expand Down Expand Up @@ -756,7 +820,7 @@ def del(path, filter=nil)
# @param [String] type identifier of the linked resource
# @param [Occi::Core::Attributes] link attributes
# @param [Array<String>] link mixins
# @return [Occi::Core::Link] link instance
# @return [Occi::Core::Link] link instance
def link(kind, source, target_location, target_kind, attributes=Occi::Core::Attributes.new, mixins=[])
link = Occi::Core::Link.new(kind)
link.mixins = mixins
Expand All @@ -774,10 +838,10 @@ def link(kind, source, target_location, target_kind, attributes=Occi::Core::Attr
# Checks whether the given endpoint URI is valid and adds a trailing
# slash if necessary.
#
# @example
# @example
# prepare_endpoint "http://localhost:3300" # => "http://localhost:3300/"
#
# @param [String] endpoint URI in a non-canonical string
# @param [String] endpoint URI in a non-canonical string
# @return [String] canonical endpoint URI in a string, with a trailing slash
def prepare_endpoint(endpoint)
raise 'Endpoint not a valid URI' if (endpoint =~ URI::ABS_URI).nil?
Expand Down Expand Up @@ -891,7 +955,7 @@ def set_media_type
end
end

# Generates a human-readable response message based on the HTTP response code.
# Generates a human-readable response message based on the HTTP response code.
#
# @example
# response_message self.class.delete(@endpoint + path)
Expand Down
41 changes: 26 additions & 15 deletions lib/occi/collection.rb
Expand Up @@ -6,14 +6,14 @@ class Collection
# Initialize a new OCCI Collection by initializing all supplied OCCI objects
#
# @param [Hash] collection including one or more of the keys kinds, mixins, actions, resources, links
def initialize(collection={ }, model = Occi::Model.new)
def initialize(collection={}, model = Occi::Model.new)
collection = Hashie::Mash.new(collection) unless collection.kind_of? Occi::Collection

@kinds = Occi::Core::Kinds.new
@mixins = Occi::Core::Mixins.new
@actions = Occi::Core::Actions.new
@kinds = Occi::Core::Kinds.new
@mixins = Occi::Core::Mixins.new
@actions = Occi::Core::Actions.new
@resources = Occi::Core::Resources.new
@links = Occi::Core::Links.new
@links = Occi::Core::Links.new

self.model = model if model

Expand All @@ -29,25 +29,25 @@ def ==(category)
not intersect(category).empty?
end

# @return [Array] categories combined list of all kinds, mixins and actions
# @return [Occi::Core::Categories] categories combined list of all kinds, mixins and actions
def categories
@kinds + @mixins + @actions
Occi::Core::Categories.new(@kinds + @mixins + @actions)
end

# @return [Array] entities combined list of all resources and links
# @return [Occi::Core::Entities] entities combined list of all resources and links
def entities
@resources + @links
Occi::Core::Entities.new(@resources + @links)
end

# @param [Occi::Core::Model] model
# @return [Occi::Core::Model]
def model=(model)
@model = model
@kinds.model = model
@mixins.model = model
@actions.model = model
@model = model
@kinds.model = model
@mixins.model = model
@actions.model = model
@resources.model = model
@links.model = model
@links.model = model
end

def check
Expand Down Expand Up @@ -122,8 +122,19 @@ def empty?
@kinds.empty? && @mixins.empty? && @actions.empty? && @resources.empty? && @links.empty? && @action.nil?
end

# Returns a collection with all categories related to the specified category
#
# @param [Occi::Core::Category] category
# @return [Occi::Core::Collection]
def get_related_to(category)
collection = self.class.new
collection.kinds = @kinds.get_related_to(category)
collection.mixins = @mixins.get_related_to(category)
collection
end

# @return [Hashie::Mash] json representation
def as_json(options = { })
def as_json(options = {})
collection = Hashie::Mash.new
collection.kinds = @kinds.collect { |kind| kind.as_json } if @kinds.any?
collection.mixins = @mixins.collect { |mixin| mixin.as_json } if @mixins.any?
Expand Down
10 changes: 9 additions & 1 deletion lib/occi/core/categories.rb
Expand Up @@ -17,6 +17,14 @@ def join(separator)
self.to_a.join(separator)
end

# Returns a Set with all categories related to the specified category
#
# @param [Occi::Core::Category] category
# @return [Occi::Core::Categories]
def get_related_to(category)
self.class.new select { |cat| cat.related_to? category }
end

# @param [Occi::Model] model
# @return [Occi::Model]
def model=(model)
Expand All @@ -26,7 +34,7 @@ def model=(model)

# @param [Hash] options
# @return [Hashie::Mash] json representation
def as_json(options={ })
def as_json(options={})
self.to_a.as_json
end

Expand Down
27 changes: 17 additions & 10 deletions lib/occi/core/category.rb
Expand Up @@ -16,9 +16,9 @@ def initialize(scheme='http://schemas.ogf.org/occi/core#',
term='category',
title=nil,
attributes=Occi::Core::Attributes.new)
@scheme = scheme
@term = term
@title = title
@scheme = scheme
@term = term
@title = title
@attributes = Occi::Core::AttributeProperties.parse attributes
end

Expand All @@ -36,7 +36,7 @@ def self.get_class(scheme, term, related=['http://schemas.ogf.org/occi/core#enti
parent = related.first.class
else
related_scheme, related_term = related.first.to_s.split '#'
parent = self.get_class related_scheme, related_term
parent = self.get_class related_scheme, related_term
end

uri = URI.parse(scheme)
Expand All @@ -62,7 +62,7 @@ def self.get_class(scheme, term, related=['http://schemas.ogf.org/occi/core#enti
end
else
klass = namespace.const_set term.classify, Class.new(parent)
klass.kind = Occi::Core::Kind.new scheme, term, nil, { }, related unless parent.ancestors.include? Occi::Core::Category
klass.kind = Occi::Core::Kind.new scheme, term, nil, {}, related unless parent.ancestors.include? Occi::Core::Category
end

klass
Expand All @@ -79,18 +79,25 @@ def type_identifier
end

# check if category is related to another category
# a category is related to another category
# if it is included in @related or
# if it is the category itself
#
# @param [String, Category] category Related Category or its type identifier
# @return [true,false] true if category is related to category_id else false
def related_to?(category)
self.related.each do |cat|
return true if cat.to_s == category.to_s
end if @related
if @related
self.related.each do |cat|
return true if cat.to_s == category.to_s
end
return true if self.to_s == category.to_s
end
false
end

# @param [Hash] options
# @return [Hashie::Mash] json representation
def as_json(options={ })
def as_json(options={})
category = Hashie::Mash.new
category.scheme = @scheme if @scheme
category.term = @term if @term
Expand Down Expand Up @@ -118,7 +125,7 @@ def to_text

# @return [Hash] hash containing the HTTP headers of the text/occi rendering
def to_header
{ :Category => self.to_string }
{:Category => self.to_string}
end

# @return [String] json representation
Expand Down
4 changes: 2 additions & 2 deletions lib/occi/model.rb
Expand Up @@ -76,10 +76,10 @@ def unregister(category)

# Return all categories from model. If filter is present, return only the categories specified by filter
#
# @param [Occi::Collection] filter
# @param [Occi::Collection,Occi::Core::Category,String] filter
# @return [Occi::Collection] collection
def get(filter = nil)
filter ? intersect(filter) : self
filter ? self.get_related_to(filter) : self
end

end
Expand Down
9 changes: 9 additions & 0 deletions spec/occi/collection_spec.rb
Expand Up @@ -28,5 +28,14 @@ module Occi
expect { collection.check }.to_not raise_error
end

it 'successfully gets all categories related to a category' do
collection = Occi::Collection.new
collection.kinds << Occi::Core::Resource.kind
collection.kinds << Occi::Core::Link.kind
collection.get_related_to(Occi::Core::Entity.kind).should == collection
collection.get_related_to(Occi::Core::Resource.kind).kinds.first.should == Occi::Core::Resource.kind
collection.get_related_to(Occi::Core::Link.kind).kinds.first.should == Occi::Core::Link.kind
end

end
end

0 comments on commit 4134458

Please sign in to comment.