private void computeLinkFanouts() {
        // Table name -> link field name -> average number of links per owning object.
        Map<String, Map<String, MutableFloat>> dbLinkFanoutMap =
            new HashMap<String, Map<String, MutableFloat>>();
        
        m_logger.info("Computing link fanouts");
        for (TableDefinition tableDef : m_appDef.getTableDefinitions().values()) {
            Map<String, MutableFloat> tableLinkFanoutMap = new HashMap<String, MutableFloat>();
            dbLinkFanoutMap.put(tableDef.getTableName(), tableLinkFanoutMap);
            computeLinkFanouts(tableDef, tableLinkFanoutMap);
        }
        
        m_dbSuppressedFieldMap = new HashMap<String, Set<String>>();
        Set<FieldDefinition> decidedLinkSet = new HashSet<FieldDefinition>();
        for (TableDefinition tableDef : m_appDef.getTableDefinitions().values()) {
            Set<String> tableSuppFieldSet = m_dbSuppressedFieldMap.get(tableDef.getTableName());
            if (tableSuppFieldSet == null) {
                tableSuppFieldSet = new HashSet<String>();
                m_dbSuppressedFieldMap.put(tableDef.getTableName(), tableSuppFieldSet);
            }
            
            Map<String, MutableFloat> tableLinkFanoutMap =
                dbLinkFanoutMap.get(tableDef.getTableName());
            for (FieldDefinition fieldDef : tableDef.getFieldDefinitions()) {
                if (!fieldDef.isLinkField() || decidedLinkSet.contains(fieldDef)) {
                    continue;
                }

                float linkFanout = 0;
                if (tableLinkFanoutMap != null) {
                    MutableFloat avgLinks = tableLinkFanoutMap.get(fieldDef.getName());
                    if (avgLinks != null) {
                        linkFanout = avgLinks.m_value;
                    }
                }
                
                TableDefinition invTableDef = tableDef.getLinkExtentTableDef(fieldDef);
                FieldDefinition invFieldDef = invTableDef.getFieldDef(fieldDef.getLinkInverse());
                float invLinkFanout = 0;
                Map<String, MutableFloat> invTableLinkFanoutMap =
                   dbLinkFanoutMap.get(invTableDef.getTableName());
                if (invTableLinkFanoutMap != null) {
                    MutableFloat avgLinks = invTableLinkFanoutMap.get(invFieldDef.getName());
                    if (avgLinks != null) {
                        invLinkFanout = avgLinks.m_value;
                    }
                }
                
                // If this link's fanout is higher than or equal to that of its inverse,
                // we'll suppress this link, otherwise the inverse. When the fanouts are
                // the same or very close, it's arbitrary which one we pick, really.
                if (linkFanout >= invLinkFanout) {
                    // Suppress this link.
                    tableSuppFieldSet.add(fieldDef.getName());
                    m_logger.info("Will suppress {}.{} and dump {}.{}", 
                                   new Object[] {tableDef.getTableName(), fieldDef.getName(),
                                                 invTableDef.getTableName(), invFieldDef.getName()});
                } else {
                    // Suppress the inverse.
                    Set<String> invTableSuppFieldSet = m_dbSuppressedFieldMap.get(invTableDef.getTableName());
                    if (invTableSuppFieldSet == null) {
                        invTableSuppFieldSet = new HashSet<String>();
                        m_dbSuppressedFieldMap.put(invTableDef.getTableName(), invTableSuppFieldSet);
                    }
                    invTableSuppFieldSet.add(invFieldDef.getName());
                    m_logger.info("Will suppress {}.{} and dump {}.{}",
                                   new Object[]{invTableDef.getTableName(), invFieldDef.getName(),
                                                tableDef.getTableName(), fieldDef.getName()});
                }
                
                decidedLinkSet.add(fieldDef);
                decidedLinkSet.add(invFieldDef);
            }
        }
    }
private void computeLinkFanouts ( ) { Map < String , Map < String , MutableFloat > > dbLinkFanoutMap = new HashMap < String , Map < String , MutableFloat > > ( ) ; m_logger . info ( "Computing link fanouts" ) ; for ( TableDefinition tableDef : m_appDef . getTableDefinitions ( ) . values ( ) ) { Map < String , MutableFloat > tableLinkFanoutMap = new HashMap < String , MutableFloat > ( ) ; dbLinkFanoutMap . put ( tableDef . getTableName ( ) , tableLinkFanoutMap ) ; computeLinkFanouts ( tableDef , tableLinkFanoutMap ) ; } m_dbSuppressedFieldMap = new HashMap < String , Set < String > > ( ) ; Set < FieldDefinition > decidedLinkSet = new HashSet < FieldDefinition > ( ) ; for ( TableDefinition tableDef : m_appDef . getTableDefinitions ( ) . values ( ) ) { Set < String > tableSuppFieldSet = m_dbSuppressedFieldMap . get ( tableDef . getTableName ( ) ) ; if ( tableSuppFieldSet == null ) { tableSuppFieldSet = new HashSet < String > ( ) ; m_dbSuppressedFieldMap . put ( tableDef . getTableName ( ) , tableSuppFieldSet ) ; } Map < String , MutableFloat > tableLinkFanoutMap = dbLinkFanoutMap . get ( tableDef . getTableName ( ) ) ; for ( FieldDefinition fieldDef : tableDef . getFieldDefinitions ( ) ) { if ( ! fieldDef . isLinkField ( ) || decidedLinkSet . contains ( fieldDef ) ) { continue ; } float linkFanout = 0 ; if ( tableLinkFanoutMap != null ) { MutableFloat avgLinks = tableLinkFanoutMap . get ( fieldDef . getName ( ) ) ; if ( avgLinks != null ) { linkFanout = avgLinks . m_value ; } } TableDefinition invTableDef = tableDef . getLinkExtentTableDef ( fieldDef ) ; FieldDefinition invFieldDef = invTableDef . getFieldDef ( fieldDef . getLinkInverse ( ) ) ; float invLinkFanout = 0 ; Map < String , MutableFloat > invTableLinkFanoutMap = dbLinkFanoutMap . get ( invTableDef . getTableName ( ) ) ; if ( invTableLinkFanoutMap != null ) { MutableFloat avgLinks = invTableLinkFanoutMap . get ( invFieldDef . getName ( ) ) ; if ( avgLinks != null ) { invLinkFanout = avgLinks . m_value ; } } if ( linkFanout >= invLinkFanout ) { tableSuppFieldSet . add ( fieldDef . getName ( ) ) ; m_logger . info ( "Will suppress {}.{} and dump {}.{}" , new Object [ ] { tableDef . getTableName ( ) , fieldDef . getName ( ) , invTableDef . getTableName ( ) , invFieldDef . getName ( ) } ) ; } else { Set < String > invTableSuppFieldSet = m_dbSuppressedFieldMap . get ( invTableDef . getTableName ( ) ) ; if ( invTableSuppFieldSet == null ) { invTableSuppFieldSet = new HashSet < String > ( ) ; m_dbSuppressedFieldMap . put ( invTableDef . getTableName ( ) , invTableSuppFieldSet ) ; } invTableSuppFieldSet . add ( invFieldDef . getName ( ) ) ; m_logger . info ( "Will suppress {}.{} and dump {}.{}" , new Object [ ] { invTableDef . getTableName ( ) , invFieldDef . getName ( ) , tableDef . getTableName ( ) , fieldDef . getName ( ) } ) ; } decidedLinkSet . add ( fieldDef ) ; decidedLinkSet . add ( invFieldDef ) ; } } }
Compute approximate link fanouts for each table by querying up to 100 objects each.