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

jmms.plugins.SwaggerDocGen Maven / Gradle / Ivy

/*
 *  Copyright 2018 the original author or authors.
 *
 *  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 jmms.plugins;

import leap.lang.Strings;
import leap.lang.Try;
import leap.lang.io.IO;
import leap.lang.json.JSON;
import leap.lang.json.JsonArray;
import leap.lang.json.JsonObject;
import leap.lang.logging.Log;
import leap.lang.logging.LogFactory;
import org.trimou.Mustache;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

class SwaggerDocGen {

    private static final Log log = LogFactory.get(SwaggerDocGen.class);

    private static final String DEFAULT              = "Default";
    private static final String DEFINITIONS          = "definitions";
    private static final String REQUIRED             = "required";
    private static final String PROPERTIES           = "properties";
    private static final String SECURITY_DEFINITIONS = "securityDefinitions";
    private static final String SCOPES               = "scopes";
    private static final String PATHS                = "paths";
    private static final String OPERATION_ID         = "operationId";
    private static final String ID                   = "id";
    private static final String NAME                 = "name";
    private static final String TITLE                = "title";
    private static final String SUMMARY              = "summary";
    private static final String METHOD               = "method";
    private static final String PATH                 = "path";
    private static final String DESCRIPTION          = "description";
    private static final String TAGS                 = "tags";
    private static final String PERMISSIONS          = "permissions";
    private static final String GROUPS               = "groups";

    private final String dir;
    private final Path   folder;
    private final String locale;

    public SwaggerDocGen(String dir, String locale) {
        this.dir    = dir;
        this.folder = Paths.get(dir);
        this.locale = locale;
    }

    void execute(JsonObject swagger) {
        Templates templates = Templates.markdown(dir, locale);

        Try.throwUnchecked(() -> Files.createDirectories(folder));

        Map data = data(swagger);

        templates.all().forEach(template -> {
            String file;
            if(template.getName().indexOf('.') > 0) {
                file = template.getName();
            }else {
                file = template.getName() + ".md";
            }
            renderAndWriteFile(template, data, file);
        });
    }

    private void renderAndWriteFile(Mustache template, Map data, String filepath) {
        File file = folder.resolve(filepath).toFile();
        if(filepath.indexOf('/') > 0) {
            Try.throwUnchecked(() -> Files.createDirectories(file.getParentFile().toPath()));
        }
        log.debug("Render template '{}' and write to '{}'", template.getName(), filepath);
        IO.writeString(file, template.render(data));
    }

    private Map data(JsonObject swagger) {
        Map data = JSON.decodeMap(swagger.toString());
        swagger  = JsonObject.of(data);

        //operation groups
        data.put(GROUPS, groups(swagger));

        //definitions
        JsonObject definitions = swagger.getObject(DEFINITIONS);
        for(String key : definitions.keys()) {
            JsonObject definition = definitions.getObject(key);

            if(Strings.isEmpty(definition.getString(TITLE))) {
                definition.asMap().put(TITLE, title(definition, key));
            }

            JsonArray required = definition.getArray(REQUIRED);
            if(null != required) {
                JsonObject props = definition.getObject(PROPERTIES);
                List names = required.asList();
                for(String name : names) {
                    JsonObject prop = props.getObject(name);
                    prop.asMap().put(REQUIRED, true);
                }
            }
        }

        //permissions
        Map permissions = new LinkedHashMap<>();
        JsonObject securities = swagger.getObject(SECURITY_DEFINITIONS);
        if(null != securities) {
            for(String key : securities.keys()) {
                JsonObject security = securities.getObject(key);

                JsonObject scopes = security.getObject(SCOPES);
                if(null != scopes) {
                    permissions.putAll(scopes.asMap());
                }
            }
        }
        data.put(PERMISSIONS, permissions);

        return data;
    }

    private Map groups(JsonObject swagger) {
        final Map map = new LinkedHashMap<>();

        prepare(map, swagger);

        int index=1;

        JsonObject paths = swagger.getObject(PATHS);
        for(String pt : paths.keys()) {
            JsonObject path = paths.getObject(pt);

            for(String method : path.keys()) {
                JsonObject   op   = path.getObject(method);
                List tags = tags(op);

                Map operation = op.asMap();
                operation.put(ID,     "op" + index++);
                operation.put(METHOD, method.toUpperCase());
                operation.put(PATH,   pt);

                String title = title(op, "");
                if(Strings.isEmpty(title)) {
                    title = Strings.firstNotEmpty(op.getString(OPERATION_ID), method.toUpperCase() + " " + pt);
                }
                operation.put(TITLE, title);

                for(String tag : tags) {
                    map.get(tag).addOperation(operation);
                }
            }
        }

        List empties = new ArrayList<>();
        for(String name : map.keySet()) {
            if(map.get(name).getOperations().isEmpty()) {
                empties.add(name);
            }
        }
        empties.forEach(name -> map.remove(name));

        OpsGroup defaultGroup = map.remove(DEFAULT);
        Map groups = new LinkedHashMap<>(map);
        if(null != defaultGroup) {
            groups.put(DEFAULT, defaultGroup);
        }

        return groups;
    }

    private List tags(JsonObject op) {
        List tagNames;
        JsonArray tags = op.getArray(TAGS);
        if(null != tags) {
            tagNames = tags.asList();
        }else {
            tagNames = new ArrayList<>();
        }
        if(tagNames.isEmpty()) {
            tagNames.add(DEFAULT);
        }
        return tagNames;
    }

    private void prepare(Map map, JsonObject swagger) {
        JsonArray tags = swagger.getArray(TAGS);
        if(null == tags || tags.isEmpty()) {
            map.put(DEFAULT, new OpsGroup(DEFAULT));
        }else {
            tags.forEach(tag -> {
                OpsGroup group = new OpsGroup(tag.asJsonObject());;
                map.put(group.getName(), group);
            });
        }
    }

    private static String title(JsonObject o, String defaults) {
        String s = Strings.firstNotEmpty(o.getString(TITLE), o.getString("x-" + TITLE));
        if(Strings.isEmpty(s)) {
            s = Strings.firstNotEmpty(o.getString(SUMMARY), o.getString("x-" + SUMMARY));
        }
        if(Strings.isEmpty(s)) {
            s = defaults;
        }
        return s;
    }

    private static String titleOrDesc(JsonObject o, String defaults) {
        String s = Strings.firstNotEmpty(o.getString(TITLE), o.getString("x-" + TITLE));
        if(Strings.isEmpty(s)) {
            s = Strings.firstNotEmpty(o.getString(SUMMARY), o.getString("x-" + SUMMARY));
        }
        if(Strings.isEmpty(s)) {
            s = o.getString(DESCRIPTION);
        }
        if(Strings.isEmpty(s)) {
            s = defaults;
        }
        return s;
    }

    private static class OpsGroup {
        private final String    name;
        private final String    title;
        private final String    description;
        private final List operations = new ArrayList<>();

        public OpsGroup(String name) {
            this.name = name;
            this.description = name;
            this.title = name;
        }

        public OpsGroup(JsonObject tag) {
            this.name        = tag.getString(NAME);
            this.description = Strings.isEmpty(tag.getString(DESCRIPTION)) ? this.name : tag.getString(DESCRIPTION);
            this.title       = titleOrDesc(tag, name);
        }

        public String getName() {
            return name;
        }

        public String getTitle() {
            return title;
        }

        public String getDescription() {
            return description;
        }

        public List getOperations() {
            return operations;
        }

        public void addOperation(Map operation) {
            operations.add(operation);
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy