Index: /ruby/trunk/lib/models/rm/data_types/quantity.rb
===================================================================
--- /ruby/trunk/lib/models/rm/data_types/quantity.rb	(revision 146)
+++ /ruby/trunk/lib/models/rm/data_types/quantity.rb	(revision 147)
@@ -177,10 +177,17 @@
             end
           end
+
           def +(other)
-            raise NotImplementError, '+ operator must be overloaded'
+            unless self.is_strictly_comparable_to?(other)
+              raise ArgumentError, 'type mismatch'
+            end
+            return DV_Amount.new(@magnitude+other.magnitude, @magnitude_status,
+                                 @accuracy, @accuracy_percent, @normal_range,
+                                 @normal_status, @other_reference_ranges)
           end
 
           def -(other)
-            raise NotImplementError, '- operator must be overloaded'
+            other.magnitude = - other.magnitude
+            self+(other)
           end
 
@@ -240,15 +247,20 @@
 # accuracy???
           def +(other)
-            unless self.is_strictly_comparable_to?(other)
-              raise ArgumentError, 'type mismatch'
-            end
-            return DV_Quantity.new(@magnitude+other.magnitude, @units,
+            dv_amount = super(other)
+            return DV_Quantity.new(dv_amount.magnitude, @units,
                                    @magnitude_status, @precision,
                                    @accuracy, @accuracy_percent, @normal_range,
                                    @normal_status, @other_reference_ranges)
           end
-          def -(other)
-            other.magnitude = - other.magnitude
-            self+(other)
+        end
+
+        class DV_Count < DV_Amount
+          def is_strictly_comparable_to?(others)
+            return false if others.nil?
+            if others.instance_of?(DV_Count)
+              return true
+            else
+              return false
+            end
           end
         end
@@ -293,4 +305,83 @@
           end
         end # end of Proportion_Kind
+
+        class DV_Proportion < DV_Amount
+          include Proportion_Kind
+          attr_reader :numerator, :denominator, :type, :precision
+
+          def initialize(numerator, denominator, type, precision=nil,
+                         magnitude_status=nil, accuracy=nil,
+                         accuracy_percent=nil, normal_range=nil,
+                         normal_status = nil, other_reference_ranges=nil)
+            self.type = type
+            self.numerator = numerator
+            self.denominator = denominator
+            self.precision = precision
+          end
+
+          def numerator=(numerator)
+            raise ArgumentError, 'numerator should not be nil' if numerator.nil?
+            if (@type == PK_FRACTION || @type == PK_INTEGER_FRACTION) &&
+                !numerator.integer?
+              raise ArgumentError, 'numerator invalid for type'
+            end
+            @numerator = numerator
+          end
+
+          def denominator=(denominator)
+            if denominator.nil? or denominator == PK_RATIO
+              raise ArgumentError, 'denominator invalid'
+            end
+            if (@type == PK_FRACTION || @type == PK_INTEGER_FRACTION) &&
+                !denominator.integer?
+              raise ArgumentError, 'denominator invalid for type'
+            end
+            if @type == PK_UNITARY && denominator != 1
+              raise ArgumentError, 'denominator invalid for type'
+            end
+            if @type == PK_PERCENT && denominator != 100
+              raise ArgumentError, 'denominator invaild for type'
+            end
+            @denominator = denominator
+          end
+
+          def type=(type)
+            if Proportion_Kind.valid_proportion_kind?(type)
+              @type = type
+            else
+              raise ArgumentError, 'type invalid'
+            end
+          end
+
+          def magnitude
+            return numerator.to_f/denominator.to_f
+          end
+
+          def precision=(precision)
+            unless precision.nil?
+              unless precision == 0 || self.is_integral?
+                @precision = precision
+              else
+                raise ArgumentError, 'precision invalid'
+              end
+            end
+          end
+
+          def is_integral?
+            return denominator.integer? && numerator.integer?
+          end
+
+          def is_strictly_comparable_to?(other)
+            unless other.instance_of?(DV_Proportion)
+              return false
+            end
+            if other.type == @type
+              return true
+            else
+              return false
+            end
+          end
+        end # end of DV_Proportion
+
       end # of Quantity
     end # of Data_Types
Index: /ruby/trunk/lib/models/tests/rm/test_data_types.rb
===================================================================
--- /ruby/trunk/lib/models/tests/rm/test_data_types.rb	(revision 146)
+++ /ruby/trunk/lib/models/tests/rm/test_data_types.rb	(revision 147)
@@ -183,4 +183,8 @@
     assert_nothing_raised(Exception){
       @dv_quantity = OpenEHR::RM::Data_Types::Quantity::DV_Quantity.new(3, 'mg', '~')}
+    assert_nothing_raised(Exception){
+      @dv_count = OpenEHR::RM::Data_Types::Quantity::DV_Count.new(1)}
+    assert_nothing_raised(Exception){
+      @dv_proportion = OpenEHR::RM::Data_Types::Quantity::DV_Proportion.new(2,3,0)}
    end
 
@@ -195,4 +199,6 @@
      assert_instance_of OpenEHR::RM::Data_Types::Quantity::DV_Amount, @dv_amount
      assert_instance_of OpenEHR::RM::Data_Types::Quantity::DV_Quantity, @dv_quantity
+     assert_instance_of OpenEHR::RM::Data_Types::Quantity::DV_Count, @dv_count
+     assert_instance_of OpenEHR::RM::Data_Types::Quantity::DV_Proportion, @dv_proportion
   end
 
@@ -216,5 +222,5 @@
 
   def test_dv_interval
-    assert @dv_interval.lower < @dv_interval.upper 
+    assert @dv_interval.lower < @dv_interval.upper
   end
 
@@ -298,4 +304,13 @@
   end
 
+  def test_dv_count
+    assert_equal 1, @dv_count.magnitude
+    dv_count2 = OpenEHR::RM::Data_Types::Quantity::DV_Count.new(2)
+    dv_count3 = @dv_count + dv_count2
+    assert 3, dv_count3.magnitude
+    dv_count3 = dv_count2 - @dv_count
+    assert 1, dv_count3.magnitude
+  end
+
   def test_proportion_kind
     assert_equal 0, OpenEHR::RM::Data_Types::Quantity::Proportion_Kind::PK_RATIO
@@ -309,4 +324,27 @@
     assert !OpenEHR::RM::Data_Types::Quantity::Proportion_Kind.valid_proportion_kind?(5)
   end
+
+  def test_dv_proportion
+    assert_equal 2.0, @dv_proportion.numerator
+    assert_equal 3.0, @dv_proportion.denominator
+    assert_equal 0, @dv_proportion.type
+    assert_equal 2.0/3.0, @dv_proportion.magnitude
+    assert @dv_proportion.is_integral?
+    dv_proportion2 = OpenEHR::RM::Data_Types::Quantity::DV_Proportion.new(1,3,0)
+    assert @dv_proportion.is_strictly_comparable_to?(dv_proportion2)
+    dv_proportion2 = OpenEHR::RM::Data_Types::Quantity::DV_Proportion.new(1,3,4)
+    assert !@dv_proportion.is_strictly_comparable_to?(dv_proportion2)
+    assert_raise(ArgumentError){
+      dv_proportion2 = OpenEHR::RM::Data_Types::Quantity::DV_Proportion.new(1.5,2.3,3)}
+    assert_raise(ArgumentError){
+      dv_proportion2 = OpenEHR::RM::Data_Types::Quantity::DV_Proportion.new(10,10,1)}
+    assert_nothing_raised(Exception){
+      dv_proportion2 = OpenEHR::RM::Data_Types::Quantity::DV_Proportion.new(10,1,1)}
+    assert_raise(ArgumentError){
+      dv_proportion2 = OpenEHR::RM::Data_Types::Quantity::DV_Proportion.new(10,10,2)}
+    assert_nothing_raised(Exception){
+      dv_proportion2 = OpenEHR::RM::Data_Types::Quantity::DV_Proportion.new(10,100,2)}
+  end
+
 end
 
