All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.simpleflatmapper.map.mapper.DiscriminatorEnumerable Maven / Gradle / Ivy

package org.simpleflatmapper.map.mapper;

import org.simpleflatmapper.converter.UncheckedConverter;
import org.simpleflatmapper.map.Mapper;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.MappingException;
import org.simpleflatmapper.util.Enumarable;
import org.simpleflatmapper.util.ErrorHelper;
import org.simpleflatmapper.util.Predicate;

public class DiscriminatorEnumerable implements Enumarable {

    private final PredicatedMapperWithContext[] discriminatorMappers;
    private final Enumarable sourceEnumarable;
    private final UncheckedConverter errorMessageGenerator;

    private T currentValue;
    private T nextValue;
    private Mapper currentMapper;
    private MappingContext currentMappingContext;


    public DiscriminatorEnumerable(
            PredicatedMapperWithContext[] discriminatorMappers,
            Enumarable sourceEnumarable,
            UncheckedConverter errorMessageGenerator) {
        this.discriminatorMappers = discriminatorMappers;
        this.sourceEnumarable = sourceEnumarable;
        this.errorMessageGenerator = errorMessageGenerator;
    }

    @Override
    public boolean next() {
        try {
            currentValue = nextValue;
            nextValue = null;
            while (sourceEnumarable.next()) {

                checkMapper();

                S source = sourceEnumarable.currentValue();

                if (currentMappingContext.broke(source)) {
                    if (currentValue == null) {
                        currentValue = currentMapper.map(source, currentMappingContext);
                    } else {
                        nextValue = currentMapper.map(source, currentMappingContext);
                        return true;
                    }
                } else {
                    currentMapper.mapTo(source, currentValue, currentMappingContext);
                }
            }

            return currentValue != null;
        } catch (Exception e) {
            ErrorHelper.rethrow(e);
            return false;
        }
    }

    public T currentValue() {
        return currentValue;
    }

    private void checkMapper() {
        for(PredicatedMapperWithContext pmm : discriminatorMappers ) {
            if (pmm.predicate.test(sourceEnumarable.currentValue())) {
                if (pmm.mapper != currentMapper) {
                    markAsBroken();
                    currentMapper = pmm.mapper;
                    currentMappingContext = pmm.mappingContext;
                }
                return;
            }
        }
        mapperNotFound();
    }

    private void mapperNotFound() {
        CharSequence errorMessage = errorMessageGenerator.convert(sourceEnumarable.currentValue());
        throw new MappingException("No mapper found for " + errorMessage);
    }

    private void markAsBroken() {
        for(PredicatedMapperWithContext pmm : discriminatorMappers ) {
           pmm.mappingContext.markAsBroken();
        }
    }

    public static class PredicatedMapperWithContext {
        private final Predicate predicate;
        private final Mapper mapper;
        private final MappingContext mappingContext;

        public PredicatedMapperWithContext(Predicate predicate, Mapper mapper, MappingContext mappingContext) {
            this.predicate = predicate;
            this.mapper = mapper;
            this.mappingContext = mappingContext;
        }
    }
}