# EmbeddableMappingConfiguration.java

    package org.codefilarete.stalactite.dsl.embeddable;

    import java.util.Collection;
    import java.util.List;
    import java.util.NoSuchElementException;
    import javax.annotation.Nullable;

    import org.codefilarete.reflection.ReadWritePropertyAccessPoint;
    import org.codefilarete.stalactite.dsl.RelationalMappingConfiguration;
    import org.codefilarete.stalactite.dsl.naming.ColumnNamingStrategy;
    import org.codefilarete.stalactite.dsl.naming.UniqueConstraintNamingStrategy;
    import org.codefilarete.stalactite.engine.configurer.embeddable.Inset;
    import org.codefilarete.stalactite.sql.ddl.Size;
    import org.codefilarete.stalactite.sql.statement.binder.ParameterBinder;
    import org.codefilarete.stalactite.sql.statement.binder.ParameterBinderRegistry.EnumBindType;
    import org.codefilarete.tool.collection.ReadOnlyIterator;
    import org.codefilarete.tool.function.Converter;

    /**
     * Defines elements needed to configure a mapping of an embeddable class
     *
     * @author Guillaume Mary
     */
    public interface EmbeddableMappingConfiguration<C> extends RelationalMappingConfiguration<C> {

    	Class<C> getBeanType();

    	@SuppressWarnings("squid:S1452" /* Can't remove wildcard here because it requires to create a local generic "super" type which is forbidden */)
    	@Nullable
    	EmbeddableMappingConfiguration<? super C> getMappedSuperClassConfiguration();

    	List<Linkage> getPropertiesMapping();

    	Collection<Inset<C, Object>> getInsets();

    	@Nullable
    	ColumnNamingStrategy getColumnNamingStrategy();

    	@Nullable
    	UniqueConstraintNamingStrategy getUniqueConstraintNamingStrategy();

    	/**
    	 * @return an iterable for all inheritance configurations, including this
    	 */
    	default Iterable<EmbeddableMappingConfiguration> inheritanceIterable() {

    		return () -> new ReadOnlyIterator<EmbeddableMappingConfiguration>() {

    			private EmbeddableMappingConfiguration next = EmbeddableMappingConfiguration.this;

    			@Override
    			public boolean hasNext() {
    				return next != null;
    			}

    			@Override
    			public EmbeddableMappingConfiguration next() {
    				if (!hasNext()) {
    					// comply with next() method contract
    					throw new NoSuchElementException();
    				}
    				EmbeddableMappingConfiguration result = this.next;
    				this.next = this.next.getMappedSuperClassConfiguration();
    				return result;
    			}
    		};
    	}

    	/**
    	 * Small contract for defining property configuration storage
    	 *
    	 * @param <C> property owner type
    	 * @param <O> property type
    	 */
    	interface Linkage<C, O> {

    		ReadWritePropertyAccessPoint<C, O> getAccessor();

    		@Nullable
    		String getFieldName();

    		@Nullable
    		String getColumnName();

    		@Nullable
    		Size getColumnSize();

    		Class<O> getColumnType();

    		@Nullable
    		ParameterBinder<Object> getParameterBinder();

    		/**
    		 * Gives the choice made by the user to define how to bind enum values: by name or ordinal.
    		 * @return null if no info was given
    		 */
    		@Nullable
    		EnumBindType getEnumBindType();

    		/**
    		 *
    		 * @return null if the user didn't mention nullability, then we'll make a choice for him according to property type
    		 */
    		@Nullable
    		Boolean isNullable();

    		boolean isUnique();

    		/** Indicates if this property is managed by entity constructor (information coming from user) */
    		boolean isSetByConstructor();

    		/** Indicates if this property should not be writable to database */
    		boolean isReadonly();

    		@Nullable
    		String getExtraTableName();

    		@Nullable
    		Converter<?, O> getReadConverter();

    		@Nullable
    		Converter<O, ?> getWriteConverter();
    	}
    }