def write
      @@logger.debug("stub: write called")
      
      validate
      
      
      entry = []
      
      
      
      @@logger.debug("#write: dup'ing @ldap_data")
      ldap_data = Marshal.load(Marshal.dump(@ldap_data))
      @@logger.debug("#write: dup finished @ldap_data")
      @@logger.debug("#write: expanding subtypes in @ldap_data")
      ldap_data.keys.each do |key|
        ldap_data[key].each do |value|
          if value.class == Hash
            suffix, real_value = extract_subtypes(value)
            if ldap_data.has_key? key + suffix
              ldap_data[key + suffix].push(real_value)
            else
              ldap_data[key + suffix] = real_value
            end
            ldap_data[key].delete(value)
          end
        end
      end
      @@logger.debug('#write: subtypes expanded for @ldap_data')
      
      @@logger.debug('#write: duping @data')
      data = Marshal.load(Marshal.dump(@data))
      @@logger.debug('#write: finished duping @data')
      @@logger.debug('#write: removing disallowed attributes from @data')
      bad_attrs = @data.keys - (@must+@may)
      bad_attrs.each do |removeme|
        data.delete(removeme) 
      end
      @@logger.debug('#write: finished removing disallowed attributes from @data')
      @@logger.debug('#write: expanding subtypes for @data')
      data.keys.each do |key|
        data[key].each do |value|
          if value.class == Hash
            suffix, real_value = extract_subtypes(value)
            if data.has_key? key + suffix
              data[key + suffix].push(real_value)
            else
              data[key + suffix] = real_value
            end
            data[key].delete(value)
          end
        end
      end
      @@logger.debug('#write: subtypes expanded for @data')
      if @exists
        
        action = {}
        replaceable = []
        
        
        
        @@logger.debug('#write: traversing ldap_data determining replaces and deletes')
        ldap_data.each do |pair|
          suffix = ''
          binary = 0
          name, *suffix_a = pair[0].split(/;/)
          suffix = ';'+ suffix_a.join(';') if suffix_a.size > 0
          name = @attr_methods[name]
          name = pair[0].split(/;/)[0] if name.nil? 
          value = data[name+suffix]
          
          value = [] if value.nil?
          
          binary = LDAP::LDAP_MOD_BVALUES if Base.schema.binary? name
          replaceable.push(name+suffix)
          if pair[1] != value
            
            if not value.empty?
              
              
              @@logger.debug("updating attribute of existing entry:  #{name+suffix}: #{value.inspect}")
              entry.push(LDAP.mod(LDAP::LDAP_MOD_REPLACE|binary, name + suffix, value))
            else
              
              
              @@logger.debug("removing attribute from existing entry:  #{name+suffix}")
              entry.push(LDAP.mod(LDAP::LDAP_MOD_REPLACE|binary, name + suffix, []))
            end
          end
        end
        @@logger.debug('#write: finished traversing ldap_data')
        @@logger.debug('#write: traversing data determining adds')
        data.each do |pair|
          suffix = ''
          binary = 0
          name, *suffix_a = pair[0].split(/;/)
          suffix = ';' + suffix_a.join(';') if suffix_a.size > 0
          name = @attr_methods[name]
          name = pair[0].split(/;/)[0] if name.nil? 
          value = pair[1]
          
          value = [] if value.nil?
          if not replaceable.member? name+suffix
            
            binary = LDAP::LDAP_MOD_BVALUES if Base.schema.binary? name
            @@logger.debug("adding attribute to existing entry:  #{name+suffix}: #{value.inspect}")
            
            
            entry.push(LDAP.mod(LDAP::LDAP_MOD_REPLACE|binary, name + suffix, value)) unless value.empty?
          end
        end
        @@logger.debug('#write: traversing data complete')
        Base.connection(WriteError.new(
                        "Failed to modify: '#{entry}'")) do |conn|
          @@logger.debug("#write: modifying #{@dn}")
          conn.modify(@dn, entry)
          @@logger.debug('#write: modify successful')
        end
      else 
        @@logger.debug('#write: adding all attribute value pairs')
        @@logger.debug("#write: adding #{@attr_methods[dnattr()].inspect} = #{data[@attr_methods[dnattr()]].inspect}")
        entry.push(LDAP.mod(LDAP::LDAP_MOD_ADD, @attr_methods[dnattr()], 
          data[@attr_methods[dnattr()]]))
        @@logger.debug("#write: adding objectClass = #{data[@attr_methods['objectClass']].inspect}")
        entry.push(LDAP.mod(LDAP::LDAP_MOD_ADD, 'objectClass', 
          data[@attr_methods['objectClass']]))
        data.each do |pair|
          if pair[1].size > 0  and pair[0] != 'objectClass' and pair[0] != @attr_methods[dnattr()]
            
            if Base.schema.binary? pair[0].split(/;/)[0]
              binary = LDAP::LDAP_MOD_BVALUES 
            else
              binary = 0
            end
            @@logger.debug("adding attribute to new entry:  #{pair[0].inspect}: #{pair[1].inspect}")
            entry.push(LDAP.mod(LDAP::LDAP_MOD_ADD|binary, pair[0], pair[1]))
          end
        end
        Base.connection(WriteError.new(
                        "Failed to add: '#{entry}'")) do |conn|
          @@logger.debug("#write: adding #{@dn}")
          conn.add(@dn, entry)
          @@logger.debug("#write: add successful")
          @exists = true
        end
      end
      @@logger.debug("#write: resetting @ldap_data to a dup of @data")
      @ldap_data = Marshal.load(Marshal.dump(data))
      
      
      @@logger.debug('#write: removing attributes from @ldap_data not sent in data')
      bad_attrs.each do |removeme|
        @ldap_data.delete(removeme) 
      end
      @@logger.debug('#write: @ldap_data reset complete')
      @@logger.debug('stub: write exitted')
    end