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

com.speedment.generator.translator.internal.component.CodeGenerationComponentImpl Maven / Gradle / Ivy

/**
 *
 * Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); You may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.speedment.generator.translator.internal.component;

import com.speedment.common.codegen.model.ClassOrInterface;
import com.speedment.common.injector.Injector;
import com.speedment.common.injector.annotation.Inject;
import com.speedment.common.mapstream.MapStream;
import com.speedment.generator.translator.JavaClassTranslator;
import com.speedment.generator.translator.Translator;
import com.speedment.generator.translator.TranslatorConstructor;
import com.speedment.generator.translator.TranslatorDecorator;
import com.speedment.generator.translator.component.CodeGenerationComponent;
import com.speedment.generator.translator.exception.SpeedmentTranslatorException;
import com.speedment.runtime.config.trait.HasMainInterface;
import com.speedment.runtime.config.trait.HasName;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

public final class CodeGenerationComponentImpl implements CodeGenerationComponent {

    private @Inject Injector injector;

    private final Map, Map>> map;

    public CodeGenerationComponentImpl() {
        map = new ConcurrentHashMap<>();
    }

    @SuppressWarnings("unchecked")
    @Override
    public >
        void put(Class docType, Class modelType, String key, TranslatorConstructor constructor) {
        aquireTranslatorSettings(docType, modelType, key).setConstructor(constructor);
    }

    @Override
    public >
        void add(Class docType, Class modelType, String key, TranslatorDecorator decorator) {
        aquireTranslatorSettings(docType, modelType, key).decorators().add(decorator);
    }

    @Override
    public >
        void remove(Class docType, String key) {
        aquireTranslatorSettings(docType, null, key).setConstructor(null);
    }

    private >
        TranslatorSettings aquireTranslatorSettings(Class docType, Class modelType, String key) {
        @SuppressWarnings("unchecked")
        final TranslatorSettings result = (TranslatorSettings) map
            .computeIfAbsent(docType,
                s -> new ConcurrentHashMap<>()
            ).computeIfAbsent(key, k -> new TranslatorSettings<>(k));

        return result;
    }

    @Override
    public 
        Stream> translators(DOC document) {
        return translators(document, s -> true);
    }

    @Override
    public Stream translatorKeys() {
        return map.values().stream()
            .flatMap(m -> MapStream.of(m).filterValue(s -> s.constructor != null).keys())
            .distinct();
    }

    @Override
    @SuppressWarnings("unchecked")
    public >
        Translator findTranslator(DOC document, Class modelType, String key) {
        return translators(document, key::equals)
            .findAny()
            .map(translator -> (Translator) translator)
            .orElseThrow(noTranslatorFound(document, key));
    }

    @SuppressWarnings("unchecked")
    private 
        Stream> translators(DOC document, Predicate nameFilter) {

        return MapStream.of(map)
            .filterKey(c -> c.isInstance(document))
            .values()
            .flatMap(m -> MapStream.of(m).filterKey(nameFilter).values())
            .map(s -> (TranslatorSettings) s)
            .filter(s -> s != null)
            .filter(s -> s.getConstructor() != null)
            .map(settings -> settings.createDecorated(injector, document));
    }

    private static Supplier noTranslatorFound(HasMainInterface doc, String key) {
        return () -> new SpeedmentTranslatorException(
            "Found no translator with key '"
            + key + "' for document '"
            + doc.mainInterface().getSimpleName() + "'."
        );
    }

    private final static class TranslatorSettings> {

        private final String key;
        private final List> decorators;
        private TranslatorConstructor constructor;

        public TranslatorSettings(String key) {
            this.key = requireNonNull(key);
            this.decorators = new CopyOnWriteArrayList<>();
        }

        public String key() {
            return key;
        }

        public TranslatorConstructor getConstructor() {
            return constructor;
        }

        public void setConstructor(TranslatorConstructor constructor) {
            this.constructor = constructor;
        }

        public List> decorators() {
            return decorators;
        }

        public JavaClassTranslator createDecorated(Injector injector, DOC document) {
            @SuppressWarnings("unchecked")
            final JavaClassTranslator translator
                = (JavaClassTranslator) getConstructor().apply(document);

            injector.inject(translator);
            
            decorators.stream()
                .map(injector::inject)
                .forEachOrdered(dec -> dec.apply(translator));

            return translator;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy