private void checkModifyEntry()

in interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java [664:876]


    private void checkModifyEntry( ModifyOperationContext modifyContext ) throws LdapException
    {
        Dn dn = modifyContext.getDn();
        Entry currentEntry = modifyContext.getEntry();
        List<Modification> mods = modifyContext.getModItems();

        // The first step is to check that the modifications are valid :
        // - the ATs are present in the schema
        // - The value is syntaxically correct
        //
        // While doing that, we will apply the modification to a copy of the current entry
        Entry tempEntry = currentEntry.clone();

        // Now, apply each mod one by one
        for ( Modification mod : mods )
        {
            Attribute attribute = mod.getAttribute();
            AttributeType attributeType = attribute.getAttributeType();

            assertAttributeIsModifyable( modifyContext, attributeType );

            switch ( mod.getOperation() )
            {
                case ADD_ATTRIBUTE:
                    // Check the syntax here
                    Attribute currentAttribute = tempEntry.get( attributeType );

                    // First check if the added Attribute is already present in the entry
                    // If not, we have to create the entry
                    if ( currentAttribute != null )
                    {
                        for ( Value value : attribute )
                        {
                            // At this point, we know that the attribute's syntax is correct
                            // We just have to check that the current attribute does not
                            // contains the value already
                            if ( currentAttribute.contains( value ) )
                            {
                                // This is an error.
                                String msg = I18n.err( I18n.ERR_54, value );
                                LOG.error( msg );
                                throw new LdapAttributeInUseException( msg );
                            }

                            currentAttribute.add( value );
                        }
                    }
                    else
                    {
                        // We don't check if the attribute is not in the MUST or MAY at this
                        // point, as one of the following modification can change the
                        // ObjectClasses.
                        Attribute newAttribute = attribute.clone();

                        // Check that the attribute allows null values if we don'y have any value
                        if ( ( newAttribute.size() == 0 ) && !newAttribute.isValid( attributeType ) )
                        {
                            // This is an error.
                            String msg = I18n.err( I18n.ERR_54, ( Object[] ) null );
                            LOG.error( msg );
                            throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
                        }

                        tempEntry.put( newAttribute );
                    }

                    break;

                case REMOVE_ATTRIBUTE:
                    // First check that the removed attribute exists
                    if ( !tempEntry.containsAttribute( attributeType ) )
                    {
                        String msg = I18n.err( I18n.ERR_55, attributeType );
                        LOG.error( msg );
                        throw new LdapNoSuchAttributeException( msg );
                    }

                    // We may have to remove the attribute or only some values
                    if ( attribute.size() == 0 )
                    {
                        // No value : we have to remove the entire attribute
                        tempEntry.removeAttributes( attributeType );
                    }
                    else
                    {
                        currentAttribute = tempEntry.get( attributeType );

                        // Now remove all the values
                        for ( Value value : attribute )
                        {
                            // We can only remove existing values.
                            if ( currentAttribute.contains( value ) )
                            {
                                currentAttribute.remove( value );
                            }
                            else
                            {
                                String msg = I18n.err( I18n.ERR_56, attributeType );
                                LOG.error( msg );
                                throw new LdapNoSuchAttributeException( msg );
                            }
                        }

                        // If the current attribute is empty, we have to remove
                        // it from the entry
                        if ( currentAttribute.size() == 0 )
                        {
                            tempEntry.removeAttributes( attributeType );
                        }
                    }

                    break;

                case REPLACE_ATTRIBUTE:
                    // The replaced attribute might not exist, it will then be a Add
                    // If there is no value, then the attribute will be removed
                    if ( !tempEntry.containsAttribute( attributeType ) )
                    {
                        if ( attribute.size() == 0 )
                        {
                            // Ignore the modification, as the attributeType does not
                            // exists in the entry
                            break;
                        }
                        else
                        {
                            // Create the new Attribute
                            Attribute newAttribute = createNewAttribute( attribute );

                            tempEntry.put( newAttribute );
                        }
                    }
                    else
                    {
                        if ( attribute.size() == 0 )
                        {
                            // Remove the attribute from the entry
                            tempEntry.removeAttributes( attributeType );
                        }
                        else
                        {
                            // Replace the existing values with the new values
                            // This is done by removing the Attribute
                            tempEntry.removeAttributes( attributeType );

                            // Create the new Attribute
                            Attribute newAttribute = createNewAttribute( attribute );

                            tempEntry.put( newAttribute );
                        }
                    }

                    break;
                    
                case INCREMENT_ATTRIBUTE:
                    // The incremented attribute might not exist
                    if ( !tempEntry.containsAttribute( attributeType ) )
                    {
                        throw new IllegalArgumentException( "Increment operation on a non existing attribute"
                            + attributeType );
                    }
                    else if ( !SchemaConstants.INTEGER_SYNTAX.equals( attributeType.getSyntax().getOid() ) )
                    {
                        throw new IllegalArgumentException( "Increment operation on a non integer attribute"
                            + attributeType );
                    }
                    else
                    {
                        Attribute modified = tempEntry.get( attributeType );
                        Value[] newValues = new Value[ modified.size() ];
                        int increment = 1;
                        int i = 0;
                        
                        if ( mod.getAttribute().size() != 0 )
                        {
                            increment = Integer.parseInt( mod.getAttribute().getString() );
                        }
                        
                        for ( Value value : modified )
                        {
                            int intValue = Integer.parseInt( value.getNormalized() );
                            
                            if ( intValue >= Integer.MAX_VALUE - increment )
                            {
                                throw new IllegalArgumentException( "Increment operation overflow for attribute" 
                                    + attributeType );
                            }
                            
                            newValues[i++] = new Value( Integer.toString( intValue + increment ) );
                            modified.remove( value );
                        }
                        
                        modified.add( newValues );
                    }
                    
                    break;

                default:
                    throw new IllegalArgumentException( "Unexpected modify operation " + mod.getOperation() );
            }
        }

        // Ok, we have created the modified entry. We now have to check that it's a valid
        // entry wrt the schema.
        // We have to check that :
        // - the rdn values are present in the entry
        // - the objectClasses inheritence is correct
        // - all the MUST are present
        // - all the attribute are in MUST and MAY, except fo the extensibleObeject OC
        // is present
        // - We haven't removed a part of the Rdn
        check( dn, tempEntry );
    }