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

com.github.loicoudot.java4cpp.MappingsManager Maven / Gradle / Ivy

package com.github.loicoudot.java4cpp;

import static com.github.loicoudot.java4cpp.Utils.newArrayList;
import static com.github.loicoudot.java4cpp.Utils.newHashMap;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXB;

import com.github.loicoudot.java4cpp.configuration.ClassMapping;
import com.github.loicoudot.java4cpp.configuration.Mappings;
import com.github.loicoudot.java4cpp.configuration.Namespace;

public class MappingsManager {

    private final Context context;
    private final Mappings mappings = new Mappings();
    private final Map, ClassMapping> mappingCache = newHashMap();

    public MappingsManager(Context context) {
        this.context = context;
    }

    public void start() {
        addMappingsFromSettings();
        addClassToDoFromMappings();
    }

    private void addMappingsFromSettings() {
        if (!Utils.isNullOrEmpty(context.getSettings().getMappingsFile())) {
            for (String name : context.getSettings().getMappingsFile().split(";")) {
                try {
                    InputStream is = Utils.getFileOrResource(name);
                    Mappings mapping = JAXB.unmarshal(is, Mappings.class);
                    is.close();
                    addMappings(mapping);
                } catch (IOException e) {
                    throw new RuntimeException("Failed to read mappings from settings " + e.getMessage());
                }
            }
        }
    }

    private void addClassToDoFromMappings() {
        context.getFileManager().logInfo("adding classes to wrappe from mappings files");
        for (ClassMapping mapping : mappings.getClasses()) {
            Class clazz = context.loadClass(mapping.getClazz());
            context.addClassToDo(clazz);
            mappingCache.put(clazz, mapping);
        }
    }

    /**
     * Add a mappings configuration bean to the actual context.
     * 
     * @param other
     *            the mappings bean to add
     */
    public void addMappings(Mappings other) {
        mappings.getKeywords().addAll(other.getKeywords());
        mappings.getClasses().addAll(other.getClasses());
        mappings.getNamespaces().addAll(other.getNamespaces());
    }

    public String escapeName(String name) {
        if (mappings.getKeywords().contains(name)) {
            return escapeName(name + '_');
        }
        return name;
    }

    /**
     * Transform the full qualified name of {@code clazz} by applying the rules
     * on namespace/package mappings. The mappings on the class name is not
     * applied here. Does not work on inner class.
     * 
     * @param clazz
     *            the class to get namespace from.
     * @return the associate namespace associate to {@code clazz}.
     */
    private List getNamespaceMapping(Class clazz) {
        int bestScore = 0;
        String bestNamespace = clazz.getName().replaceAll("\\.", "::");
        for (Namespace namespace : mappings.getNamespaces()) {
            if (namespace.getJavaPackage().length() > bestScore && clazz.getName().matches(namespace.getJavaPackage())) {
                bestScore = namespace.getJavaPackage().length();
                bestNamespace = Utils.isNullOrEmpty(namespace.getNamespace()) ? clazz.getSimpleName() : String.format("%s::%s", namespace.getNamespace(),
                        clazz.getSimpleName());
            }
        }
        return Arrays.asList(bestNamespace.split("::"));
    }

    /**
     * Return the final full qualified C++ name of the class. Apply the
     * namespace/package mapping, the class name mapping and escape all part by
     * the reserved words list. Works also for inner class.
     * 
     * @return the final full qualified C++ name.
     */
    public List getNamespace(Class clazz) {
        List namespace;
        if (clazz.getEnclosingClass() == null) {
            namespace = getNamespaceMapping(clazz);
        } else {
            Class enclosing = clazz;
            Deque> stack = new ArrayDeque>();
            while (enclosing.getEnclosingClass() != null) {
                stack.add(enclosing);
                enclosing = enclosing.getEnclosingClass();
            }
            namespace = getNamespace(enclosing);
            while (!stack.isEmpty()) {
                namespace.add(getCppName(stack.pollLast()));
            }
        }
        List escapedNamespace = newArrayList();
        for (String name : namespace) {
            escapedNamespace.add(escapeName(name));
        }
        escapedNamespace.set(escapedNamespace.size() - 1, getCppName(clazz));
        return escapedNamespace;
    }

    /**
     * Return a valid C++ name for the class {@code clazz}, by escaping reserved
     * words or by returning the name specified by the mapping or the
     * annotation.
     * 
     * @return a valid C++ class name.
     */
    public String getCppName(Class clazz) {
        ClassMapping mapping = mappingCache.get(clazz);
        Java4Cpp annotation = clazz.getAnnotation(Java4Cpp.class);

        if (mapping != null) {
            if (!Utils.isNullOrEmpty(mapping.getCppName())) {
                return mapping.getCppName();
            }
        }
        if (annotation != null && !Utils.isNullOrEmpty(annotation.name())) {
            return annotation.name();
        }
        return escapeName(clazz.getSimpleName());
    }

    public ClassMapping get(Class clazz) {
        return mappingCache.get(clazz);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy