private void processSubordinates()

in interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java [666:773]


    private void processSubordinates( OperationContext operationContext, Set<AttributeTypeOptions> returningAttributes, 
        boolean allAttributes, Entry entry ) throws LdapException
    {
        // Bypass the rootDSE : we won't get the nbChildren and nbSubordiantes for this special entry
        if ( Dn.isNullOrEmpty( entry.getDn() ) )
        {
            return;
        }

        // Add the Subordinates AttributeType if it's requested
        AttributeType nbChildrenAt = directoryService.getAtProvider().getNbChildren();
        AttributeTypeOptions nbChildrenAto = new AttributeTypeOptions( nbChildrenAt );
        AttributeType nbSubordinatesAt = directoryService.getAtProvider().getNbSubordinates();
        AttributeTypeOptions nbSubordinatesAto = new AttributeTypeOptions( nbSubordinatesAt );
        AttributeType hasSubordinatesAt = directoryService.getAtProvider().getHasSubordinates();
        AttributeTypeOptions hasSubordinatesAto = new AttributeTypeOptions( hasSubordinatesAt );
        AttributeType structuralObjectClassAt = directoryService.getAtProvider().getStructuralObjectClass();
        AttributeTypeOptions structuralObjectClassAto = new AttributeTypeOptions( structuralObjectClassAt );
        
        if ( returningAttributes != null )
        {
            boolean nbChildrenRequested = returningAttributes.contains( nbChildrenAto ) || allAttributes;
            boolean nbSubordinatesRequested = returningAttributes.contains( nbSubordinatesAto ) || allAttributes;
            boolean hasSubordinatesRequested = returningAttributes.contains( hasSubordinatesAto ) || allAttributes;
            boolean structuralObjectClassRequested = returningAttributes.contains( structuralObjectClassAto ) || allAttributes;

            if ( nbChildrenRequested || nbSubordinatesRequested || hasSubordinatesRequested 
                || structuralObjectClassRequested )
            {
                Partition partition = directoryService.getPartitionNexus().getPartition( entry.getDn() );
                Subordinates subordinates = partition.getSubordinates( operationContext.getTransaction(), entry );
                
                long nbChildren = subordinates.getNbChildren();
                long nbSubordinates = subordinates.getNbSubordinates();
                
                // Inject the nbChildren OpAttr if needed
                if ( nbChildrenRequested )
                {
                    entry.add( new DefaultAttribute( nbChildrenAt, 
                        Long.toString( nbChildren ) ) );
                }
    
                // Inject the nbSubordinates OpAttr if needed
                if ( nbSubordinatesRequested )
                { 
                    entry.add( new DefaultAttribute( nbSubordinatesAt,
                        Long.toString( nbSubordinates ) ) );
                }
                
                // Inject the hasSubordinates OpAttr if needed
                if ( hasSubordinatesRequested )
                { 
                    if ( nbSubordinates > 0 )
                    {
                        entry.add( new DefaultAttribute( hasSubordinatesAt, "TRUE" ) );
                    }
                    else
                    {
                        entry.add( new DefaultAttribute( hasSubordinatesAt, "FALSE" ) );
                    }
                }

                // Inject the structuralObjectclass OpAttr if needed
                if ( structuralObjectClassRequested )
                {
                    Attribute objectClasses = entry.get( SchemaConstants.OBJECT_CLASS_AT );
                    Map<String, ObjectClass> superiors = new HashMap<>();
                    ObjectClass[] objectClassArray = new ObjectClass[objectClasses.size()];
                    int nbStructural = 0;
                    
                    // First get all the structural objectClasses
                    for ( Value objectClassValue : objectClasses )
                    {
                        ObjectClass objectClass = 
                            schemaManager.getObjectClassRegistry().get( objectClassValue.getNormalized() );
                        
                        if ( objectClass.isStructural() )
                        {
                            objectClassArray[nbStructural++] = objectClass;
                            
                            // We can only have one superior objectClass for Structural ObjectClass
                            superiors.put( objectClass.getSuperiors().get( 0 ).getOid(), objectClass );
                        }
                    }

                    // Then find the top of them
                    if ( nbStructural == 1 )
                    {
                        entry.add( new DefaultAttribute( structuralObjectClassAt, 
                            objectClassArray[0].getName() ) );
                    }
                    else
                    {
                        for ( ObjectClass oc : objectClassArray )
                        {
                            if ( !superiors.containsKey( oc.getOid() ) )
                            {
                                // We are done : the current OC is not the superior of any other
                                // OC, this is necessarily the top level one
                                entry.add( new DefaultAttribute( structuralObjectClassAt, oc.getName() ) );
                                break;
                            }
                        }
                    }
                }
            }
        }
    }