class CompositeQueryLogic extends BaseQueryLogic<Object> {

    @Override
    public GenericQueryConfiguration initialize(Connector connection, Query settings, Set<Authorizations> runtimeQueryAuthorizations) throws Exception {
        
        for (BaseQueryLogic<?> logic : queryLogics) {
            final BaseQueryLogic<?> queryLogic = logic;
            int count = CollectionUtils.countMatches(
                            queryLogics,
                            object -> {
                                if (object instanceof BaseQueryLogic<?>) {
                                    if (queryLogic.getClass().equals(((BaseQueryLogic<?>) object).getClass())
                                                    && queryLogic.getTableName().equals(((BaseQueryLogic<?>) object).getTableName())) {
                                        return true;
                                    } else {
                                        return false;
                                    }
                                } else {
                                    return false;
                                }
                            });
            
            if (count > 1) {
                throw new RuntimeException("More than one instance of query logic class configured with the same table: " + logic.getClass().getName());
            }
        }
        
        Iterator<BaseQueryLogic<?>> itr = queryLogics.iterator();
        StringBuilder logicQueryStringBuilder = new StringBuilder("CompositeQueryLogic: ");
        while (itr.hasNext()) {
            BaseQueryLogic<?> logic = itr.next();
            GenericQueryConfiguration config = null;
            try {
                config = logic.initialize(connection, settings, runtimeQueryAuthorizations);
                logicQueryStringBuilder.append("(table=" + config.getTableName());
                logicQueryStringBuilder.append(",query=" + config.getQueryString());
                logicQueryStringBuilder.append(") ");
                QueryLogicHolder holder = new QueryLogicHolder(logic.getClass().getSimpleName());
                holder.setConfig(config);
                holder.setSettings(settings);
                holder.setMaxResults(logic.getMaxResults());
                logicState.put(logic, holder);
            } catch (Exception e) {
                log.info(e.getMessage() + " removing query logic " + logic.getClass().getName() + " from CompositeQuery");
                itr.remove();
                if (itr.hasNext() == false && logicState.isEmpty()) {
                    // all logics have failed to initialize, rethrow the last exception caught
                    throw new IllegalStateException("All logics have failed to initialize", e);
                }
            }
        }
        startLatch = new CountDownLatch(logicState.values().size());
        completionLatch = new CountDownLatch(logicState.values().size());
        this.results = new CompositeQueryLogicResults(Math.min(settings.getPagesize() * 2, 1000), completionLatch);
        if (log.isDebugEnabled()) {
            log.debug("CompositeQuery initialized with the following queryLogics: ");
            for (Entry<BaseQueryLogic<?>,QueryLogicHolder> entry : this.logicState.entrySet()) {
                log.debug("\tLogicName: " + entry.getKey().getClass().getSimpleName() + ", tableName: " + entry.getKey().getTableName());
            }
        }
        
        final String compositeQueryString = logicQueryStringBuilder.toString();
        return new GenericQueryConfiguration() {
            @Override
            public String getQueryString() {
                return compositeQueryString;
            }
        };
    }

    public  CompositeQueryLogic();
    public  CompositeQueryLogic(CompositeQueryLogic other);

}