public static LdifFile computeDiff()

in plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/Utils.java [404:646]


    public static LdifFile computeDiff( IEntry oldEntry, IEntry newEntry )
    {
        // get connection parameters
        ModifyMode modifyMode = oldEntry.getBrowserConnection().getModifyMode();
        ModifyMode modifyModeNoEMR = oldEntry.getBrowserConnection().getModifyModeNoEMR();
        ModifyOrder modifyAddDeleteOrder = oldEntry.getBrowserConnection().getModifyAddDeleteOrder();

        // get all attribute descriptions
        Set<String> attributeDescriptions = new LinkedHashSet<>();
        
        for ( IAttribute oldAttr : oldEntry.getAttributes() )
        {
            attributeDescriptions.add( oldAttr.getDescription() );
        }
        
        for ( IAttribute newAttr : newEntry.getAttributes() )
        {
            attributeDescriptions.add( newAttr.getDescription() );
        }

        // prepare the LDIF record containing the modifications
        LdifChangeModifyRecord record = new LdifChangeModifyRecord( LdifDnLine.create( newEntry.getDn().getName() ) );
        
        if ( newEntry.isReferral() )
        {
            record.addControl( LdifControlLine.create( StudioControl.MANAGEDSAIT_CONTROL.getOid(),
                StudioControl.MANAGEDSAIT_CONTROL.isCritical(), StudioControl.MANAGEDSAIT_CONTROL.getControlValue() ) );
        }
        record.setChangeType( LdifChangeTypeLine.createModify() );

        // check all the attributes
        for ( String attributeDescription : attributeDescriptions )
        {
            // get attribute type schema information
            Schema schema = oldEntry.getBrowserConnection().getSchema();
            AttributeType atd = schema.getAttributeTypeDescription( attributeDescription );
            boolean hasEMR = SchemaUtils.getEqualityMatchingRuleNameOrNumericOidTransitive( atd, schema ) != null;
            boolean isReplaceForced = ( hasEMR && modifyMode == ModifyMode.REPLACE )
                || ( !hasEMR && modifyModeNoEMR == ModifyMode.REPLACE );
            boolean isAddDelForced = ( hasEMR && modifyMode == ModifyMode.ADD_DELETE )
                || ( !hasEMR && modifyModeNoEMR == ModifyMode.ADD_DELETE );
            boolean isOrderedValue = atd.getExtensions().containsKey( "X-ORDERED" ) //$NON-NLS-1$
                && atd.getExtensions().get( "X-ORDERED" ).contains( "VALUES" ); //$NON-NLS-1$ //$NON-NLS-2$

            // get old an new values for comparison
            IAttribute oldAttribute = oldEntry.getAttribute( attributeDescription );
            Set<String> oldValues = new HashSet<>();
            Map<String, LdifAttrValLine> oldAttrValLines = new LinkedHashMap<>();
            
            if ( oldAttribute != null )
            {
                for ( IValue value : oldAttribute.getValues() )
                {
                    LdifAttrValLine attrValLine = computeDiffCreateAttrValLine( value );
                    oldValues.add( attrValLine.getUnfoldedValue() );
                    oldAttrValLines.put( attrValLine.getUnfoldedValue(), attrValLine );
                }
            }
            
            IAttribute newAttribute = newEntry.getAttribute( attributeDescription );
            Set<String> newValues = new HashSet<>();
            Map<String, LdifAttrValLine> newAttrValLines = new LinkedHashMap<>();
            
            if ( newAttribute != null )
            {
                for ( IValue value : newAttribute.getValues() )
                {
                    LdifAttrValLine attrValLine = computeDiffCreateAttrValLine( value );
                    newValues.add( attrValLine.getUnfoldedValue() );
                    newAttrValLines.put( attrValLine.getUnfoldedValue(), attrValLine );
                }
            }

            // check what to do
            if ( oldAttribute != null && newAttribute == null )
            {
                // attribute only exists in the old entry: delete all values
                LdifModSpec modSpec;
                
                if ( isReplaceForced )
                {
                    // replace (empty value list)
                    modSpec = LdifModSpec.createReplace( attributeDescription );
                }
                else
                // addDelForced or default
                {
                    // delete all
                    modSpec = LdifModSpec.createDelete( attributeDescription );
                    for ( IValue value : oldAttribute.getValues() )
                    {
                        modSpec.addAttrVal( computeDiffCreateAttrValLine( value ) );
                    }
                }
                
                modSpec.finish( LdifModSpecSepLine.create() );
                record.addModSpec( modSpec );
            }
            else if ( oldAttribute == null && newAttribute != null )
            {
                // attribute only exists in the new entry: add all values
                LdifModSpec modSpec;
                
                if ( isReplaceForced )
                {
                    // replace (all values)
                    modSpec = LdifModSpec.createReplace( attributeDescription );
                }
                else
                // addDelForced or default 
                {
                    // add (all new values)
                    modSpec = LdifModSpec.createAdd( attributeDescription );
                }
                
                for ( IValue value : newAttribute.getValues() )
                {
                    modSpec.addAttrVal( computeDiffCreateAttrValLine( value ) );
                }
                
                modSpec.finish( LdifModSpecSepLine.create() );
                record.addModSpec( modSpec );
            }
            else if ( oldAttribute != null && newAttribute != null && !oldValues.equals( newValues ) )
            {
                // attribute exists in both entries, check modifications
                if ( isReplaceForced )
                {
                    // replace (all new values)
                    LdifModSpec modSpec = LdifModSpec.createReplace( attributeDescription );
                    
                    for ( IValue value : newAttribute.getValues() )
                    {
                        modSpec.addAttrVal( computeDiffCreateAttrValLine( value ) );
                    }
                    
                    modSpec.finish( LdifModSpecSepLine.create() );
                    record.addModSpec( modSpec );
                }
                else
                {
                    // compute diff
                    List<LdifAttrValLine> toDel = new ArrayList<>();
                    List<LdifAttrValLine> toAdd = new ArrayList<>();

                    for ( Map.Entry<String, LdifAttrValLine> entry : oldAttrValLines.entrySet() )
                    {
                        if ( !newValues.contains( entry.getKey() ) )
                        {
                            toDel.add( entry.getValue() );
                        }
                    }
                    
                    for ( Map.Entry<String, LdifAttrValLine> entry : newAttrValLines.entrySet() )
                    {
                        if ( !oldValues.contains( entry.getKey() ) )
                        {
                            toAdd.add( entry.getValue() );
                        }
                    }

                    /*
                     *  we use add/del in the following cases:
                     *  - add/del is forced in the connection configuration
                     *  - for attributes w/o X-ORDERED 'VALUES'
                     *  
                     *  we use replace in the following cases:
                     *  - for attributes with X-ORDERED 'VALUES'
                     */
                    if ( isAddDelForced || !isOrderedValue )
                    {
                        // add/del del/add
                        LdifModSpec addModSpec = LdifModSpec.createAdd( attributeDescription );
                        
                        for ( LdifAttrValLine attrValLine : toAdd )
                        {
                            addModSpec.addAttrVal( attrValLine );
                        }
                        
                        addModSpec.finish( LdifModSpecSepLine.create() );
                        LdifModSpec delModSpec = LdifModSpec.createDelete( attributeDescription );
                        
                        for ( LdifAttrValLine attrValLine : toDel )
                        {
                            delModSpec.addAttrVal( attrValLine );
                        }
                        
                        delModSpec.finish( LdifModSpecSepLine.create() );

                        if ( modifyAddDeleteOrder == ModifyOrder.DELETE_FIRST )
                        {
                            if ( delModSpec.getAttrVals().length > 0 )
                            {
                                record.addModSpec( delModSpec );
                            }
                            
                            if ( addModSpec.getAttrVals().length > 0 )
                            {
                                record.addModSpec( addModSpec );
                            }
                        }
                        else
                        {
                            if ( addModSpec.getAttrVals().length > 0 )
                            {
                                record.addModSpec( addModSpec );
                            }
                            
                            if ( delModSpec.getAttrVals().length > 0 )
                            {
                                record.addModSpec( delModSpec );
                            }
                        }
                    }
                    else
                    {
                        // replace (all new values)
                        LdifModSpec modSpec = LdifModSpec.createReplace( attributeDescription );
                        
                        for ( LdifAttrValLine attrValLine : newAttrValLines.values() )
                        {
                            modSpec.addAttrVal( attrValLine );
                        }
                        
                        modSpec.finish( LdifModSpecSepLine.create() );
                        record.addModSpec( modSpec );
                    }
                }
            }

        }

        record.finish( LdifSepLine.create() );

        LdifFile model = new LdifFile();
        
        if ( record.isValid() && record.getModSpecs().length > 0 )
        {
            model.addContainer( record );
        }
        
        return model.getRecords().length > 0 ? model : null;
    }