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

com.bixuebihui.jsongen.EsJsonschema2Pojo Maven / Gradle / Ivy

package com.bixuebihui.jsongen;

import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.sun.codemodel.*;
import org.apache.commons.io.FilenameUtils;

import org.apache.commons.io.output.StringBuilderWriter;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.text.CaseUtils;
import org.jsonschema2pojo.*;
import org.jsonschema2pojo.exception.GenerationException;
import org.jsonschema2pojo.rules.RuleFactory;
import org.jsonschema2pojo.util.NameHelper;
import org.jsonschema2pojo.util.URLUtil;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Consumer;

import static org.apache.commons.lang3.StringUtils.*;

/**
 * @author xwx
 */
public class EsJsonschema2Pojo {

    /**
     * Reads the contents of the given source and initiates schema generation.
     *
     * @param config           the configuration options (including source and target paths,
     *                         and other behavioural options) that will control code
     *                         generation
     * @param primaryKeyFields
     * @return
     * @throws FileNotFoundException if the source path is not found
     * @throws IOException           if the application is unable to read data from the source
     */
    public static Map generate(GenEs config, RuleLogger logger,
                                               Consumer> indexFieldsConsumer,
                                               Set ignoreFields, Set collectionFields,
                                               Map additionalProperties, List primaryKeyFields) throws IOException {
        Annotator annotator = getAnnotator(config);
        RuleFactory ruleFactory = createRuleFactory(config);

        ruleFactory.setAnnotator(annotator);
        ruleFactory.setGenerationConfig(config);
        ruleFactory.setLogger(logger);
        ruleFactory.setSchemaStore(new SchemaStore(createContentResolver(config, additionalProperties)));

        EsSchemaMapper mapper = new EsSchemaMapper(ruleFactory, createSchemaGenerator(config));

        JCodeModel codeModel = new JCodeModel();

        if (config.isRemoveOldOutput()) {
            removeOldOutput(config.getTargetDirectory());
        }

        boolean mkdir = config.getTargetDirectory().exists() || config.getTargetDirectory().mkdirs();

        Map map = new HashMap<>(64);

        for (Iterator sources = config.getSource(); sources.hasNext(); ) {
            URL source = sources.next();

            if (URLUtil.parseProtocol(source.toString()) == URLProtocol.FILE && URLUtil.getFileFromURL(source).isDirectory()) {
                generateRecursive(config, mapper, codeModel, defaultString(config.getTargetPackage()),
                        Arrays.asList(URLUtil.getFileFromURL(source).listFiles(config.getFileFilter())), ignoreFields, collectionFields);
            } else {

                String className = getNodeName(source, config);
                if (config.getAlias() != null) {
                    className = config.getAlias();
                }

                JType res = mapper.generate(codeModel, className,
                        defaultString(config.getTargetPackage()), source, ignoreFields, collectionFields,
                        additionalProperties.get(GenEs.USERNAME), additionalProperties.get(GenEs.PASSWORD)
                );


                String[] fields = findFields((JDefinedClass) res);
                if (primaryKeyFields != null) {
                    for (int i = 0; i < fields.length; i++) {
                        String p = CaseUtils.toCamelCase(fields[i], false, '_', '-');
                        String type = findTypes((JDefinedClass) res, p);

                        if (type != null && primaryKeyFields.contains(fields[i])) {
                            map.put(fields[i], type);
                        }
                    }
                }

                if (indexFieldsConsumer != null) {
                    indexFieldsConsumer.accept(ImmutablePair.of(res.name(), fields));
                }

            }
        }

        if (mkdir) {
            CodeWriter sourcesWriter = new FileCodeWriterWithEncoding(config.getTargetDirectory(), config.getOutputEncoding());
            CodeWriter resourcesWriter = new FileCodeWriterWithEncoding(config.getTargetDirectory(), config.getOutputEncoding());
            codeModel.build(sourcesWriter, resourcesWriter);
        } else {
            throw new GenerationException("Could not create or access target directory " + config.getTargetDirectory().getAbsolutePath());
        }
        return map;
    }

    private static String findTypes(JDefinedClass res, String field) {
        return res.fields().containsKey(field) ? res.fields().get(field).type().name() : null;
    }

    private static String[] findFields(JDefinedClass res) {
        StringBuilderWriter sb = new StringBuilderWriter();
        JFormatter f = new JFormatter(sb);
        for (JAnnotationUse annotation : res.annotations()) {
            if ("JsonPropertyOrder".equals(annotation.getAnnotationClass().name())) {
                List list = (List) ((JAnnotationArrayMember) (annotation.getAnnotationMembers().get("value"))).annotations();
                for (JAnnotationValue a : list) {
                    a.generate(f);
                    System.out.println(((JAnnotationStringValue) a).getValue());
                }
            }
        }

        StringBuilder s = sb.getBuilder();
        return s.substring(1, s.length() - 1).split("\"\"");
    }

    private static ContentResolver createContentResolver(GenEs config, Map additionalProperties) {
        if (config.getSourceType() == SourceType.YAMLSCHEMA || config.getSourceType() == SourceType.YAML) {
            return new ContentResolver(new YAMLFactory());
        } else {
            return new EsContentResolver(null, additionalProperties);
        }
    }

    private static SchemaGenerator createSchemaGenerator(GenEs config) {
        if (config.getSourceType() == SourceType.YAMLSCHEMA || config.getSourceType() == SourceType.YAML) {
            return new SchemaGenerator(new YAMLFactory());
        } else {
            return new SchemaGenerator();
        }
    }

    private static RuleFactory createRuleFactory(GenEs config) {
        Class clazz = config.getCustomRuleFactory();

        if (!RuleFactory.class.isAssignableFrom(clazz)) {
            throw new IllegalArgumentException("The class name given as a rule factory  (" + clazz.getName() + ") does not refer to a class that implements " + RuleFactory.class.getName());
        }

        try {
            return clazz.getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    private static void generateRecursive(GenEs config, EsSchemaMapper mapper, JCodeModel codeModel, String packageName, List schemaFiles, Set ignoreFields, Set collectionFields) throws IOException {

        schemaFiles.sort(config.getSourceSortOrder().getComparator());

        for (File child : schemaFiles) {
            if (child.isFile()) {

                String className = getNodeName(child.toURI().toURL(), config);

                if (config.getAlias() != null) {
                    className = config.getAlias();
                }

                packageName = defaultString(packageName);

                mapper.generate(codeModel, className, packageName,
                        child.toURI().toURL(), ignoreFields, collectionFields, config.getUsername(), config.getPassword());


            } else {
                generateRecursive(config, mapper, codeModel,
                        childQualifiedName(packageName, child.getName()),
                        Arrays.asList(child.listFiles(config.getFileFilter())), ignoreFields, collectionFields);
            }
        }
    }

    private static String childQualifiedName(String parentQualifiedName, String childSimpleName) {
        String safeChildName = childSimpleName.replaceAll(NameHelper.ILLEGAL_CHARACTER_REGEX, "_");
        return isEmpty(parentQualifiedName) ? safeChildName : parentQualifiedName + "." + safeChildName;
    }

    private static void removeOldOutput(File targetDirectory) {
        if (targetDirectory.exists()) {
            for (File f : targetDirectory.listFiles()) {
                delete(f);
            }
        }
    }

    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE")
    private static void delete(File f) {
        if (f.isDirectory()) {
            for (File child : f.listFiles()) {
                delete(child);
            }
        }
        f.delete();
    }

    private static Annotator getAnnotator(GenEs config) {
        AnnotatorFactory factory = new AnnotatorFactory(config);
        return factory.getAnnotator(factory.getAnnotator(config.getAnnotationStyle()), factory.getAnnotator(config.getCustomAnnotator()));
    }

    public static String getNodeName(URL file, GenEs config) {

        // extract index name
        String url = file.toString();
        if (url.startsWith("http") && url.contains("/_mapping")) {
            url = url.substring(0, url.indexOf("/_mapping"));
        } else if (url.startsWith("http") && url.contains("/_search")) {
            url = url.substring(0, url.indexOf("/_search"));
        }

        return getNodeName(url, config);
    }

    public static String getNodeName(String filePath, GenEs config) {
        try {
            String fileName = FilenameUtils.getName(URLDecoder.decode(filePath, StandardCharsets.UTF_8.toString()));
            String[] extensions = config.getFileExtensions() == null ? new String[]{} : config.getFileExtensions();

            boolean extensionRemoved = false;
            for (String s : extensions) {
                String extension = s;
                if (extension.length() == 0) {
                    continue;
                }
                if (!extension.startsWith(".")) {
                    extension = "." + extension;
                }
                if (fileName.endsWith(extension)) {
                    fileName = removeEnd(fileName, extension);
                    extensionRemoved = true;
                    break;
                }
            }
            if (!extensionRemoved) {
                fileName = FilenameUtils.getBaseName(fileName);
            }
            return fileName;
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(String.format("Unable to generate node name from URL: %s", filePath), e);
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy