# ManyToManyEntityOptionsSupport.java

    package org.codefilarete.stalactite.engine.configurer.entity;

    import java.util.Collection;
    import java.util.function.Supplier;

    import org.codefilarete.reflection.SerializablePropertyAccessor;
    import org.codefilarete.reflection.SerializablePropertyMutator;
    import org.codefilarete.stalactite.dsl.entity.FluentMappingBuilderManyToManyJoinTableOptions;
    import org.codefilarete.stalactite.dsl.entity.FluentMappingBuilderManyToManyOptions;
    import org.codefilarete.stalactite.dsl.relation.ManyToManyEntityOptions;
    import org.codefilarete.stalactite.engine.configurer.manytomany.ManyToManyRelation;
    import org.codefilarete.stalactite.engine.configurer.onetomany.OneToManyRelation;

    /**
     * A small class for one-to-many options storage into a {@link OneToManyRelation}. Acts as a wrapper over it.
     */
    public class ManyToManyEntityOptionsSupport<C, I, O, S1 extends Collection<O>, S2 extends Collection<C>>
    		implements ManyToManyEntityOptions<C, O, S1, S2> {

    	private final ManyToManyRelation<C, O, I, S1, S2> manyToManyRelation;

    	public ManyToManyEntityOptionsSupport(ManyToManyRelation<C, O, I, S1, S2> manyToManyRelation) {
    		this.manyToManyRelation = manyToManyRelation;
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> initializeWith(Supplier<S1> collectionFactory) {
    		manyToManyRelation.setCollectionFactory(collectionFactory);
    		return null;    // we can return null because dispatcher will return proxy
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> reverselySetBy(SerializablePropertyMutator<O, C> reverseLink) {
    		manyToManyRelation.getMappedByConfiguration().setReverseCombiner(reverseLink);
    		return null;    // we can return null because dispatcher will return proxy
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> reverseCollection(SerializablePropertyAccessor<O, S2> collectionAccessor) {
    		manyToManyRelation.getMappedByConfiguration().setReverseCollectionAccessor(collectionAccessor);
    		return null;    // we can return null because dispatcher will return proxy
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> reverseCollection(SerializablePropertyMutator<O, S2> collectionMutator) {
    		manyToManyRelation.getMappedByConfiguration().setReverseCollectionMutator(collectionMutator);
    		return null;    // we can return null because dispatcher will return proxy
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> reverselyInitializeWith(Supplier<S2> collectionFactory) {
    		manyToManyRelation.getMappedByConfiguration().setReverseCollectionFactory(collectionFactory);
    		return null;    // we can return null because dispatcher will return proxy
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> cascading(RelationMode relationMode) {
    		manyToManyRelation.setRelationMode(relationMode);
    		return null;    // we can return null because dispatcher will return proxy
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> fetchSeparately() {
    		manyToManyRelation.fetchSeparately();
    		return null;    // we can return null because dispatcher will return proxy
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> indexedBy(String columnName) {
    		manyToManyRelation.setIndexingColumnName(columnName);
    		return null;
    	}

    	@Override
    	public FluentMappingBuilderManyToManyOptions<C, I, O, S1, S2> indexed() {
    		manyToManyRelation.ordered();
    		return null;
    	}

    	@Override
    	public FluentMappingBuilderManyToManyJoinTableOptions<C, I, O, S1, S2> joinTable(String tableName) {
    		manyToManyRelation.setAssociationTableName(tableName);
    		return null;
    	}
    }