io.github.robwin.swagger2markup.builder.document.DefinitionsDocument.java Source code

Java tutorial

Introduction

Here is the source code for io.github.robwin.swagger2markup.builder.document.DefinitionsDocument.java

Source

/*
 *
 *  Copyright 2015 Robert Winkler
 *
 *  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 io.github.robwin.swagger2markup.builder.document;

import io.swagger.models.Model;
import io.swagger.models.Swagger;
import io.swagger.models.properties.Property;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.swagger2markup.utils.PropertyUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * @author Robert Winkler
 */
public class DefinitionsDocument extends MarkupDocument {

    private static final String DEFINITIONS = "Definitions";
    private static final List<String> IGNORED_DEFINITIONS = Collections.singletonList("Void");
    private static final String JSON_SCHEMA = "JSON Schema";
    private static final String XML_SCHEMA = "XML Schema";
    private static final String JSON_SCHEMA_EXTENSION = ".json";
    private static final String XML_SCHEMA_EXTENSION = ".xsd";
    private static final String JSON = "json";
    private static final String XML = "xml";
    private static final String DESCRIPTION_FILE_NAME = "description";
    private boolean schemasEnabled;
    private String schemasFolderPath;
    private boolean handWrittenDescriptionsEnabled;
    private String descriptionsFolderPath;

    public DefinitionsDocument(Swagger swagger, MarkupLanguage markupLanguage, String schemasFolderPath,
            String descriptionsFolderPath) {
        super(swagger, markupLanguage);
        if (StringUtils.isNotBlank(schemasFolderPath)) {
            this.schemasEnabled = true;
            this.schemasFolderPath = schemasFolderPath;
        }
        if (StringUtils.isNotBlank(descriptionsFolderPath)) {
            this.handWrittenDescriptionsEnabled = true;
            this.descriptionsFolderPath = descriptionsFolderPath + "/" + DEFINITIONS.toLowerCase();
        }
        if (schemasEnabled) {
            if (logger.isDebugEnabled()) {
                logger.debug("Include schemas is enabled.");
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("Include schemas is disabled.");
            }
        }
        if (handWrittenDescriptionsEnabled) {
            if (logger.isDebugEnabled()) {
                logger.debug("Include hand-written descriptions is enabled.");
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("Include hand-written descriptions is disabled.");
            }
        }
    }

    @Override
    public MarkupDocument build() throws IOException {
        definitions(swagger.getDefinitions());
        return this;
    }

    /**
     * Builds the Swagger definitions.
     *
     * @param definitions the Swagger definitions
     */
    private void definitions(Map<String, Model> definitions) throws IOException {
        if (MapUtils.isNotEmpty(definitions)) {
            this.markupDocBuilder.sectionTitleLevel1(DEFINITIONS);
            for (Map.Entry<String, Model> definitionsEntry : definitions.entrySet()) {
                String definitionName = definitionsEntry.getKey();
                if (StringUtils.isNotBlank(definitionName)) {
                    if (checkThatDefinitionIsNotInIgnoreList(definitionName)) {
                        definition(definitionName, definitionsEntry.getValue());
                        definitionSchema(definitionName);
                        if (logger.isInfoEnabled()) {
                            logger.info("Definition processed: {}", definitionName);
                        }
                    } else {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Definition was ignored: {}", definitionName);
                        }
                    }
                }
            }
        }
    }

    /**
     * Checks that the definition is not in the list of ignored definitions.
     *
     * @param definitionName the name of the definition
     * @return true if the definition can be processed
     */
    private boolean checkThatDefinitionIsNotInIgnoreList(String definitionName) {
        return !IGNORED_DEFINITIONS.contains(definitionName);
    }

    /**
     * Builds a concrete definition
     *
     * @param definitionName the name of the definition
     * @param model the Swagger Model of the definition
     */
    private void definition(String definitionName, Model model) throws IOException {
        this.markupDocBuilder.sectionTitleLevel2(definitionName);
        descriptionSection(definitionName, model);
        propertiesSection(definitionName, model);

    }

    private void propertiesSection(String definitionName, Model model) throws IOException {
        Map<String, Property> properties = model.getProperties();
        List<String> headerAndContent = new ArrayList<>();
        List<String> header = Arrays.asList(NAME_COLUMN, DESCRIPTION_COLUMN, REQUIRED_COLUMN, SCHEMA_COLUMN,
                DEFAULT_COLUMN);
        headerAndContent.add(StringUtils.join(header, DELIMITER));
        if (MapUtils.isNotEmpty(properties)) {
            for (Map.Entry<String, Property> propertyEntry : properties.entrySet()) {
                Property property = propertyEntry.getValue();
                String propertyName = propertyEntry.getKey();
                List<String> content = Arrays.asList(propertyName,
                        propertyDescription(definitionName, propertyName, property),
                        Boolean.toString(property.getRequired()), PropertyUtils.getType(property, markupLanguage),
                        PropertyUtils.getDefaultValue(property));
                headerAndContent.add(StringUtils.join(content, DELIMITER));
            }
            this.markupDocBuilder.tableWithHeaderRow(headerAndContent);
        }
    }

    private void descriptionSection(String definitionName, Model model) throws IOException {
        if (handWrittenDescriptionsEnabled) {
            String description = handWrittenPathDescription(definitionName.toLowerCase(), DESCRIPTION_FILE_NAME);
            if (StringUtils.isNotBlank(description)) {
                this.markupDocBuilder.paragraph(description);
            } else {
                if (logger.isInfoEnabled()) {
                    logger.info(
                            "Hand-written description cannot be read. Trying to use description from Swagger source.");
                }
                modelDescription(model);
            }
        } else {
            modelDescription(model);
        }
    }

    private void modelDescription(Model model) {
        String description = model.getDescription();
        if (StringUtils.isNotBlank(description)) {
            this.markupDocBuilder.paragraph(description);
        }
    }

    private String propertyDescription(String definitionName, String propertyName, Property property)
            throws IOException {
        String description;
        if (handWrittenDescriptionsEnabled) {
            description = handWrittenPathDescription(
                    definitionName.toLowerCase() + "/" + propertyName.toLowerCase(), DESCRIPTION_FILE_NAME);
            if (StringUtils.isBlank(description)) {
                if (logger.isInfoEnabled()) {
                    logger.info(
                            "Hand-written description file cannot be read. Trying to use description from Swagger source.");
                }
                description = StringUtils.defaultString(property.getDescription());
            }
        } else {
            description = StringUtils.defaultString(property.getDescription());
        }
        return description;
    }

    /**
     * Reads a hand-written description
     *
     * @param descriptionFolder the name of the folder where the description file resides
     * @param descriptionFileName the name of the description file
     * @return the content of the file
     * @throws IOException
     */
    private String handWrittenPathDescription(String descriptionFolder, String descriptionFileName)
            throws IOException {
        for (String fileNameExtension : markupLanguage.getFileNameExtensions()) {
            java.nio.file.Path path = Paths.get(descriptionsFolderPath, descriptionFolder,
                    descriptionFileName + fileNameExtension);
            if (Files.isReadable(path)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Description file processed: {}", path);
                }
                return FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim();
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Description file is not readable: {}", path);
                }
            }
        }
        if (logger.isWarnEnabled()) {
            logger.info("No description file found with correct file name extension in folder: {}",
                    Paths.get(descriptionsFolderPath, descriptionFolder));
        }
        return null;
    }

    private void definitionSchema(String definitionName) throws IOException {
        if (schemasEnabled) {
            if (StringUtils.isNotBlank(definitionName)) {
                schema(JSON_SCHEMA, schemasFolderPath, definitionName + JSON_SCHEMA_EXTENSION, JSON);
                schema(XML_SCHEMA, schemasFolderPath, definitionName + XML_SCHEMA_EXTENSION, XML);
            }
        }
    }

    private void schema(String title, String schemasFolderPath, String schemaName, String language)
            throws IOException {
        java.nio.file.Path path = Paths.get(schemasFolderPath, schemaName);
        if (Files.isReadable(path)) {
            this.markupDocBuilder.sectionTitleLevel3(title);
            this.markupDocBuilder.source(FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim(),
                    language);
            if (logger.isInfoEnabled()) {
                logger.info("Schema file processed: {}", path);
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("Schema file is not readable: {}", path);
            }
        }
    }
}