deltacloud-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mfoj...@redhat.com
Subject [PATCH core 04/11] CIMI: Initial addition of attribute validation for CIMI models
Date Mon, 11 Feb 2013 12:35:45 GMT
From: Michal Fojtik <mfojtik@redhat.com>

This addition will make possible to specify the 'required => true'
option for all attributes in CIMI models, like:

class Machine < Base
  text :name, :required => true
end

To run a check if the instance of Machine is valid or not you can do
following:

Machine.from_xml(xml_body).validate!

This method will raise the CIMI::Model::ValidationError exception if
attribute marked as 'required' have no value set.

Signed-off-by: Michal fojtik <mfojtik@redhat.com>
---
 server/lib/cimi/models/base.rb     | 26 ++++++++++++++++++++++++++
 server/lib/cimi/models/resource.rb |  4 ++++
 server/lib/cimi/models/schema.rb   | 22 ++++++++++++++++++++--
 3 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index a96909f..1f519dc 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -78,6 +78,24 @@ require_relative '../helpers/database_helper'
 
 module CIMI::Model
 
+  class ValidationError < StandardError
+
+    def initialize(attribute)
+      @attr_name  = attribute
+      super("Required attribute '#{@attr_name}' must be set.")
+    end
+
+    # Report the ValidationError as HTTP 400 - Bad Request
+    def code
+      400
+    end
+
+    def name
+      @attr_name
+    end
+
+  end
+
   class Base < Resource
 
     # Extend the base model with database methods
@@ -123,6 +141,14 @@ module CIMI::Model
       self
     end
 
+    def validate!(format=:xml)
+      self.class.required_attributes.each do |attr|
+        unless attr.valid?(send(attr.name))
+          raise CIMI::Model::ValidationError.new(attr.send("#{format}_name"))
+        end
+      end
+    end
+
     # FIXME: Kludge around the fact that we do not have proper *Create
     # objects that deserialize properties by themselves
     def extract_properties!(data)
diff --git a/server/lib/cimi/models/resource.rb b/server/lib/cimi/models/resource.rb
index 3271c5e..d7eceec 100644
--- a/server/lib/cimi/models/resource.rb
+++ b/server/lib/cimi/models/resource.rb
@@ -145,6 +145,10 @@ module CIMI
           xml["resourceURI"] = resource_uri
           XmlSimple.xml_out(xml, :root_name => xml_tag_name)
         end
+
+        def required_attributes
+          @schema.required_attributes
+        end
       end
 
       # END of class methods
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index 5a5d2c9..7260b81 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -24,11 +24,13 @@ class CIMI::Model::Schema
   #
   class Attribute
     attr_reader :name, :xml_name, :json_name
+    attr_reader :required
 
     def initialize(name, opts = {})
       @name = name
       @xml_name = opts[:xml_name] || name.to_s.camelize(true)
       @json_name = opts[:json_name] || name.to_s.camelize(true)
+      @required = opts[:required] || false
     end
 
     def from_xml(xml, model)
@@ -50,6 +52,14 @@ class CIMI::Model::Schema
     def convert(value)
       value
     end
+
+    def required?
+      @required
+    end
+
+    def valid?(value)
+      !value.nil? and !value.empty?
+    end
   end
 
   class Scalar < Attribute
@@ -122,7 +132,7 @@ class CIMI::Model::Schema
       else
         @schema = CIMI::Model::Schema.new
         @schema.instance_eval(&block) if block_given?
-        @schema.scalar(content, :text => :direct) if content
+        @schema.scalar(content, :text => :direct, :required => opts[:required]) if
content
       end
     end
 
@@ -178,6 +188,10 @@ class CIMI::Model::Schema
       end
     end
 
+    def valid?(value)
+      @schema.required_attributes.any? { |a| a.valid?(value.send(a.name) )}
+    end
+
     private
     def struct
       if @klass
@@ -369,6 +383,10 @@ class CIMI::Model::Schema
     @attributes.map { |a| a.name }
   end
 
+  def required_attributes
+    @attributes.select { |a| a.required? }
+  end
+
   #
   # The DSL
   #
@@ -387,7 +405,7 @@ class CIMI::Model::Schema
 
     def href(*args)
       opts = args.extract_opts!
-      args.each { |arg| struct(arg, opts) { scalar :href } }
+      args.each { |arg| struct(arg, opts) { scalar :href, :required => opts[:required]
} }
     end
 
     def text(*args)
-- 
1.8.1.2


Mime
View raw message