<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -29,7 +29,7 @@ module App
       end
     end
 
-    private
+    protected
 
     ##
     # Get a list of naked fieldlet record, all belonging to a single instance
@@ -45,7 +45,8 @@ module App
         # If we just loaded our link fieldlet (if applicable), save it as
         # the &quot;old&quot; duplicant's ID
         if flet_class == ::Fieldlets::LinkFieldlet
-          @old_duplicant_id = f[:int_value]
+          @duplicant_id = @old_duplicant_id = f[:int_value]
+
         end
       end
     end
@@ -140,7 +141,7 @@ module App
 
       return false if changed.empty?
       
-      #save_duplication!
+      save_duplication!
 			
       @fieldlets.each do |fid, fieldlet|
         fieldlet[:instance_id] = @instance_id
@@ -155,7 +156,7 @@ module App
       return true
     end
 
-    private
+    protected
 
     # Fetch the duplicant from the DataContainer's extra entities
     #
@@ -182,7 +183,7 @@ module App
     #
     #
     def destroy
-      #destroy_duplicate() if self.class::DUPLICATION
+      destroy_duplicate() if self.class::DUPLICATION
       Fieldlet.filter(:entity_id =&gt; @entity[:id],
         :instance_id =&gt; @instance_id).delete
 				
@@ -191,7 +192,7 @@ module App
     
 		
     # == ClassMethods
-    private
+    protected
 		
     def self.generate_instance_id
       ((Time.now.to_f * 1000).to_i &lt;&lt; 16) + rand(1024 * 64)</diff>
      <filename>app/models/app/field.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,25 +10,103 @@ module App
   class Field
 
     def create_duplicate()
+      # Get the duplicate field class.
+      # This should raise an exception if the other entity isn't found or is not
+      # of a supported kind for this link.
       duplicant_field = get_target_field()
-      
+
+      self.class::FIELDLET_IDS.each_with_index do |id, i|
+        fieldlet = @fieldlets[id]
+        next if !fieldlet
+
+        target_fieldlet_kind = duplicant_field::FIELDLET_IDS[i]
+        
+        target_fieldlet = Fieldlet.new()
+
+        values = fieldlet.values.dup
+        values.merge!({:entity_id =&gt; @duplicant_id,
+                       :kind =&gt; target_fieldlet_kind, 
+                       :instance_id =&gt; @instance_id})
+
+        values[:int_value] = @entity[:id] if fieldlet.class == ::Fieldlets::LinkFieldlet
+
+        values.each do|key,value|
+          target_fieldlet[key] = value
+        end
+
+        target_fieldlet.save_changes()
+      end
     end
 
-    def get_target_field
-      duplicant = self.duplicant()
-      raise DuplicantNotFoundException if !duplicant
+    def update_duplicate()
+      # If the duplicant's value changed, then we handle it differently
+      if self.duplicant_changed?
 
-      target_field = self.class::DUPLICATION[duplicant.class]
-      raise DuplicantKindMismatchException.new(duplicant.class) if !target_field
+        # Destroy the old instance
+        self.destroy_duplicate(@old_duplicant_id)
 
+        # Create a new instance for the new duplicant
+        self.create_duplicate()
+
+        # We're done
+        return
+      end
       
-    end
+      duplicant_field = get_target_field()
 
+      # Update or create fieldlets on the other side
+      self.class::FIELDLET_IDS.each_with_index do |id, i|
+        fieldlet = @fieldlets[id]
+        next if !fieldlet || !fieldlet.changed?
 
+        # Get the target fieldlet kind
+        target_fieldlet_kind = duplicant_field::FIELDLET_IDS[i]
 
+        flet_pk = {:entity_id =&gt; @duplicant_id,
+                   :kind =&gt; target_fieldlet_kind,
+                   :instance_id =&gt; @instance_id}
 
+        if fieldlet.new?
+          # New fieldlets require the target fieldlet to be created
+          target_fieldlet = Fieldlet.new()
 
+          values = fieldlet.values.dup
+          values.merge!(flet_pk)
 
+          values.each do |key,value|
+            target_fieldlet[key] = value
+          end
+
+        else
+          # The target fieldlet already exists, so we need to update it
+          # Load it with the primary key we need (this didn't change)
+          target_fieldlet = Fieldlet.load(flet_pk)
+
+          # Now update the values that were changed
+          fieldlet.changed_columns.each do |col|
+            target_fieldlet[col] = fieldlet[col]
+          end
+        end
+
+        target_fieldlet.save_changes()
+      end
+      
+    end
+
+    # Get the duplicate field class for this field.
+    # This is accomplished by looking at the &quot;other&quot; entity's (loaded previously)
+    # metadata.
+    def get_target_field
+      # Get the &quot;other&quot; entity from the data container (loaded previously)
+      duplicant = self.duplicant()
+      raise DuplicantNotFoundException if !duplicant
+
+      # Get the duplicant field class from metadata
+      target_field = self.class::DUPLICATION[duplicant.class]
+      raise DuplicantKindMismatchException.new(duplicant.class) if !target_field
+
+      return target_field
+    end
 
 
 
@@ -52,147 +130,9 @@ module App
     # @param [App::Entity] duplicant (optional)
     #
     def destroy_duplicate(duplicant = self.duplicant())
-      ns()::Fieldlet.filter(:instance_id =&gt; self.instance_id(),
+      Fieldlet.filter(:instance_id =&gt; self.instance_id(),
         :entity_id =&gt; duplicant[:id]).delete
     end
 
-
-
-
-
-
-    ##
-    # Updates the duplicants for the given field instance
-    #
-    # @param [Fixnum] instance_id 64bit instance_id to act upon
-    #
-    # === Notes
-    # * If the duplicant entity has changed, we need to delete the currently
-    #   duplicated instance from the older linked duplicant, and create new
-    #   duplicated instance for the new entity
-    #
-    # * If the duplicant hasn't changed, we only update the duplicated instance's
-    #   fieldlets and call #save_changes @see set_duplicants_values!
-    def update_duplicates!(instance_id)
-      if duplicant_changed?
-        destroy_duplicates!(self.link_fieldlet.old_entity)
-        create_duplicates!(instance_id)
-        return
-      end
-      set_duplicants_values!(instance_id)
-      @duplicated_fieldlets.each{|f| f.new? ? f.save : f.save_changes}
-    end
-		
-    ##
-    # Creates the duplicants for the given field instance
-    #
-    # @param [Fixnum] instance_id 64bit instance_id to act upon
-    #
-    #
-    def create_duplicates!(instance)
-      set_duplicants_values!(instance,true) # true for creating duplicates
-      @duplicated_fieldlets.each{|f| f.save}
-    end
-		
-    ##
-    # Updates the duplicants for the given field instance
-    #
-    # @param [Fixnum] instance_id 64bit instance_id to act upon
-    # @param [Boolean] force_create true for creating fieldlets, false for
-    #                  updating
-    #
-    #
-		 
-    def set_duplicants_values!(instance_id, force_create = false)
-      @duplicated_fieldlets = []
-			
-      fieldlets = self.all_fieldlets
-      target_fieldlet_ids = self.duplicants_fieldlet_ids
-
-      if target_fieldlet_ids.size != fieldlets.size
-        raise &quot;duplicated fields should match!!&quot;
-      end
-			
-      fieldlets.each_with_index do |fieldlet,i|
-        next if !fieldlet.value? #skip if the fieldlet is null
-			
-        # get the original values
-        values = fieldlet.values.dup #dup because hashes are mutable
-				
-        # overide the kind and the entity_id values
-        values.merge!(:entity_id =&gt; duplicant.pk,
-          :kind =&gt; target_fieldlet_ids[i].to_i(16),
-          :instance_id_id =&gt; instance_id)
-				
-        # if we're duplicating the link fieldlet, we need to revesrse it on the
-        # duplicated version
-        if self.class::LINK_FIELDLET == fieldlet.class::IDENTIFIER
-          values.merge!(:int_value =&gt; @entity[:id])
-        end
-				
-        # now will create the fieldlet instance_ids
-        if (fieldlet.new? || force_create)
-          target_fieldlet = ns()::Fieldlet.new
-          target_fieldlet.values.merge!(values)
-        else
-          target_fieldlet = ns()::Fieldlet.load(values)
-					
-          target_fieldlet.set_changed_columns(fieldlet.changed_columns)
-        end
-        @duplicated_fieldlets &lt;&lt; target_fieldlet
-      end
-			
-      return @duplicated_fieldlets
-    end
-		
-		
-    ##
-    # Returns a list of fieldlet ids of the mirroring duplicant field
-    #
-    # @return [Array[String]] the hex encoded fieldlet ids
-    #
-    def duplicants_fieldlet_ids
-      self.duplicant_field::FIELDLET_IDS
-    end
-		
-    ##
-    # Returns the Field class of the duplicant entity, which mirrors this instance field
-    #
-    # @return [Class] the duplicant field class
-    #
-    #
-    def duplicant_field
-      @duplicant_field ||= self.class::DUPLICATION[self.duplicant.class]
-    end
-		
-    ##
-    # Returns the *current* linked entity to this instance
-    # The duplicant is the entity to which the link_fieldlet is pointing to *currently*
-    #
-    # @return [App::Entity] the linked entity
-    #
-    # === Notes
-    # * the @old_duplicant instance variable is filled upon loading of the entity, with the pointed
-    #   entity of the link, currently stored in the DB.
-    #
-    # * if we have no dupliant, we'll use the @old_duplicant
-    #
-    def duplicant
-      @duplicant ||= self.link_fieldlet.entity
-      @duplicant || @old_duplicant
-    end
-		
-    ##
-    # Return the fieldlet with the type that was defined as the link fieldlet of the field
-    # link fieldlet connects the field to the other side of the link
-    #
-    # @return [App::Fieldlet] the linked fieldlet
-    #
-    def link_fieldlet
-      @fieldlets[self.class::LINK_FIELDLET]
-    end
-		
-    #end InstanceMethods
-
   end
 end
\ No newline at end of file</diff>
      <filename>app/models/app/field/field_duplication.rb</filename>
    </modified>
    <modified>
      <diff>@@ -43,7 +43,7 @@ module App
 
 
     def changed?
-      !@changed_columns.empty?
+      !self.changed_columns.empty?
     end
 
   end</diff>
      <filename>app/models/app/fieldlet.rb</filename>
    </modified>
    <modified>
      <diff>@@ -30,7 +30,7 @@ module VM
         fieldlets.each {|elem| fieldlet_hash[elem.hex_guid] = @ns::FIELDLETS[elem.hex_guid.to_i(16)][:fieldlet_class]}
 
         # Build the FIELDLET_IDS const
-        @fieldlet_ids = fieldlets.collect{|e| e.hex_guid}
+        @fieldlet_ids = fieldlets.collect{|e| e.hex_guid.to_i(16)}
 
         # Set the consts
         self.set_consts!({'FIELDLET_IDS' =&gt; @fieldlet_ids,
@@ -88,8 +88,8 @@ module VM
        flets = {}
        
        @fieldlet_ids.each do |fid|
-         flet_schema = @ns::FIELDLETS[fid.to_i(16)]
-         flets[fid] = {
+         flet_schema = @ns::FIELDLETS[fid]
+         flets[&quot;%016x&quot; % fid] = {
                        :name =&gt; flet_schema[:name],
                        :type =&gt; flet_schema[:prefs][&quot;type&quot;],
                        :prefs =&gt; flet_schema[:prefs]</diff>
      <filename>app/models/vm/builders/field_builder.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,7 @@ STOREY =  { # Storey Publishing
     :field_id =&gt; &quot;24864cb27445ef74&quot;, # Products
     :data =&gt; {
       # Product             =&gt;  PIXMA
-      '344715e69dfefe30' =&gt; '000000622ec11c68'
+      '344715e69dfefe30' =&gt; '000000622ec11c68',
     }
   },
 
@@ -38,6 +38,10 @@ STOREY =  { # Storey Publishing
 }
 
 describe &quot;Entity updates&quot; do
+  #
+  # Helper methods
+  #
+
   def match_instance_data(instance, data)
     instance.fieldlets.each do |id, flet|
       flet.value.should == data[&quot;%016x&quot; % id]
@@ -57,10 +61,40 @@ describe &quot;Entity updates&quot; do
     instance = @entity.data_container.get_instance(instance_id)
 
     match_instance_data(instance, data)
+
+    return instance
   end
 
+  def match_duplicates(instance, duplicate_instance)
+    my_flets = instance.class::FIELDLET_IDS
+    dup_flets = duplicate_instance.class::FIELDLET_IDS
+
+    # Compare sizes
+    my_flets.size.should == dup_flets.size
+
+    my_flets.each_with_index do |flet_id, index|
+      target_flet_id = dup_flets[index]
+
+      my_flet = instance.fieldlets[flet_id]
+      target_flet = duplicate_instance.fieldlets[target_flet_id]
+
+      my_flet.class.should == target_flet.class
+
+      if my_flet.class == ::Fieldlets::LinkFieldlet
+        # Link fieldlets should have reversed values
+        my_flet.value.to_i(16).should == target_flet[:entity_id]
+        target_flet.value.to_i(16).should == my_flet[:entity_id]
+
+      else
+        my_flet.value.should == target_flet.value
+      end
+    end
+
+  end
+
+
   before(:each) do
-    FixtureHelper.load_entities(STOREY[:id])
+    FixtureHelper.load_entities(STOREY[:id], PIXMA[:id])
     @entity = ENTITY.find_with_fieldlets(STOREY[:id])
   end
 
@@ -70,7 +104,14 @@ describe &quot;Entity updates&quot; do
     @entity.add_instance(h[:field_id], h[:data])
     @entity.data_container.dirty.size.should == 1
 
-    save_reload_and_match(h[:data])
+
+    instance = save_reload_and_match(h[:data])
+
+    duplicant = ENTITY.find_with_fieldlets(PIXMA[:id])
+
+    duplicate_instance = duplicant.data_container.get_instance(instance.instance_id)
+
+    match_duplicates(instance, duplicate_instance)
   end
   
   it &quot;should Remove instances correctly&quot; do
@@ -88,8 +129,14 @@ describe &quot;Entity updates&quot; do
     # reload
     @entity = ENTITY.find_with_fieldlets(STOREY[:id])
 
+
     l = lambda{@entity.data_container.get_instance(instance_id)}
     l.should raise_error(App::InstanceNotFoundException)
+
+    
+    pixma = ENTITY.find_with_fieldlets(PIXMA[:id])
+    l = lambda{pixma.data_container.get_instance(instance_id)}
+    l.should raise_error(App::InstanceNotFoundException)
   end
   
   it &quot;should Edit instances correctly&quot; do
@@ -98,7 +145,14 @@ describe &quot;Entity updates&quot; do
     @entity.data_container.dirty.size.should == 1
     @entity.data_container.dirty.values.first.instance_id.should == h[:instance_id].to_i(16)
 
-    save_reload_and_match(h[:data])
+    instance = save_reload_and_match(h[:data])
+    
+
+    duplicant = ENTITY.find_with_fieldlets(PIXMA[:id])
+
+    duplicate_instance = duplicant.data_container.get_instance(instance.instance_id)
+
+    match_duplicates(instance, duplicate_instance)
   end
 
   
@@ -107,8 +161,6 @@ describe &quot;Entity updates&quot; do
     @entity.set_instance(h[:field_id], h[:data])
     @entity.data_container.dirty.size.should == 1
     
-    
-
     save_reload_and_match(h[:data])
   end
 </diff>
      <filename>spec/app/entity_update_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,4 +22,5 @@
   :kind: 2090736770146440206
   :title: Making Cheese, Butter &amp; Yogurt (Storey Country Wisdom Bulletin, a-283)
   :created_at: 2008-09-14 06:48:04 +03:00
-  :id: 370063338453787794
\ No newline at end of file
+  :id: 370063338453787794
+</diff>
      <filename>spec/fixtures/entities/00003143d85874f5.yml</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>f58bdeddb520775fe6919f3964531ffd838a9d8b</id>
    </parent>
  </parents>
  <author>
    <name>Gilad</name>
    <email>giladvdn@gmail.com</email>
  </author>
  <url>http://github.com/shlomiatar/nifty-vm/commit/5820262aebd9c498c2cb612efc9e327212bb7961</url>
  <id>5820262aebd9c498c2cb612efc9e327212bb7961</id>
  <committed-date>2009-05-07T13:01:14-07:00</committed-date>
  <authored-date>2009-05-07T13:01:14-07:00</authored-date>
  <message>Duplication fixes and specs.</message>
  <tree>6cf590ff716bbe32d58a653e861f94c9990f4176</tree>
  <committer>
    <name>Gilad</name>
    <email>giladvdn@gmail.com</email>
  </committer>
</commit>
