001/*
002 * Copyright 2023 the original author or authors.
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * https://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.cuioss.test.valueobjects.contract;
017
018import java.util.List;
019import java.util.function.Function;
020
021import de.cuioss.test.valueobjects.api.VerifyMapperConfiguration;
022import de.cuioss.test.valueobjects.contract.support.MapperAttributesAsserts;
023import de.cuioss.test.valueobjects.objects.ParameterizedInstantiator;
024import de.cuioss.test.valueobjects.objects.RuntimeProperties;
025import de.cuioss.test.valueobjects.property.PropertySupport;
026import de.cuioss.tools.logging.CuiLogger;
027import lombok.NonNull;
028import lombok.RequiredArgsConstructor;
029
030/**
031 * Defines tests for Mapper
032 *
033 * @author Oliver Wolff
034 * @param <S> Source: The type of the source-Objects to be mapped from
035 * @param <T> Target: The type of the source-Objects to be mapped to
036 */
037@RequiredArgsConstructor
038public class MapperContractImpl<S, T> {
039
040    private static final CuiLogger log = new CuiLogger(MapperContractImpl.class);
041
042    @NonNull
043    private final VerifyMapperConfiguration config;
044
045    @NonNull
046    private final ParameterizedInstantiator<? extends S> sourceInstantiator;
047
048    @NonNull
049    private final RuntimeProperties targetMetadata;
050
051    @NonNull
052    private final Function<S, T> mapper;
053
054    /**
055     * Runs the asserts for the mapper tests
056     */
057    public void assertContract() {
058
059        final var builder = new StringBuilder("Verifying ");
060        builder.append(getClass().getName()).append("\nWith source-configuration: ")
061                .append(sourceInstantiator.getRuntimeProperties().toString());
062        builder.append("\nWith target-configuration: ").append(targetMetadata.toString());
063        log.info(builder.toString());
064        var asserter = new MapperAttributesAsserts(config, targetMetadata, sourceInstantiator.getRuntimeProperties());
065        handleSimpleMapping(asserter);
066    }
067
068    private void handleSimpleMapping(MapperAttributesAsserts asserter) {
069        log.info("Testing mimimal Mapping for mapper-class {}", mapper.getClass());
070        verifyMapping(asserter, sourceInstantiator.getRuntimeProperties().getRequiredAsPropertySupport(true),
071                "minimal-instance");
072        log.info("Testing full Mapping for mapper-class {}", mapper.getClass());
073        verifyMapping(asserter, sourceInstantiator.getRuntimeProperties().getWritableAsPropertySupport(true),
074                "full-instance");
075    }
076
077    private void verifyMapping(MapperAttributesAsserts asserter, List<PropertySupport> properties, String context) {
078        S source = sourceInstantiator.newInstance(properties, false);
079        var target = mapper.apply(source);
080        var names = properties.stream().map(PropertySupport::getName).toList();
081        log.debug("Verifying mapper in context of {} with attributes {}", context, names);
082        asserter.assertMappingForSourceAttributes(names, source, target);
083    }
084
085}