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

za.co.mip.ablduck.Comment Maven / Gradle / Ivy

There is a newer version: 229
Show newest version
/**
 * Copyright 2017-2023 MIP Holdings
 *
 *  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 za.co.mip.ablduck;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;

import za.co.mip.ablduck.models.Deprecated;

public class Comment {
    private String comment = "";
    private String author = "";
    private String returns = "";
    private Boolean isInternal = null;
    private Deprecated deprecated = null;
    private Map parameters = new HashMap<>();

    public String getComment() {
        return markdown(comment);
    }

    public String getAuthor() {
        return author;
    }

    public String getReturn() {
        return returns;
    }

    public Boolean isInternal() {
        return isInternal;
    }

    public Deprecated getDeprecated() {
        return deprecated;
    }

    public Map getParameters() {
        return parameters;
    }

    public void addExtraTag(Map extraTag) {
        for (Map.Entry vTag : extraTag.entrySet()) {
            this.comment += "### " + vTag.getKey() + ":\n" + vTag.getValue() + "\n";
        }
    }

    public void parseComment(String comment) {
        if (comment == null || "".equals(comment))
            return;

        if (comment.startsWith("/**") && comment.split("\n")[0].indexOf('-') == -1) {
            parseJavadocComment(comment);
        } else {
            parseABLDocComment(comment);
        }
    }

    private void parseABLDocComment(String comment) {
        // convert crlf to lf to avoid eol problems
        comment = comment.replace("\r\n", "\n");
        
        // Remove comment characters
        comment = cleanAblComment(comment);
        
        String[] commentLines = comment.split("\n");

        String tagType = null;
        String tagText = null;
        List resolvedTags = new ArrayList<>();

        for (int i = 0; i < commentLines.length; i++) {

            String commentLine = ltrim(commentLines[i]) + '\n'; // Put this back as we split on it

            // Assuming a line that starts with an @xxx is a token
            if (commentLine.startsWith("@") && !" ".equals(commentLine.substring(1, 2))) {

                // Store previous tag if we had one
                if (tagType != null)
                    resolvedTags.add(new Tag(tagType, tagText));

                Integer nextSpace = commentLine.indexOf(' ');

                if (nextSpace != -1) {
                    tagType = commentLine.substring(1, nextSpace);
                    tagText = ltrim(commentLine.substring(nextSpace));
                } else {
                    tagType = commentLine.substring(1);
                    tagText = "";
                }

                continue;
            }

            Integer colonPosition = commentLine.indexOf(':');

            // Potential Token in the form Token : xxxx
            if (colonPosition != -1) {
                String token = commentLine.substring(0, colonPosition).trim();

                // If there is no space in the token name, its a token.
                if (token.indexOf(' ') == -1) {

                    // Store previous tag if we had one
                    if (tagType != null)
                        resolvedTags.add(new Tag(tagType, tagText));

                    tagType = token;
                    tagText = ltrim(commentLine.substring(colonPosition + 1));

                    continue;
                }
            }
            if (tagType != null)
                tagText += " " + commentLine;
            else
                this.comment += commentLine;

        }

        // Store previous tag if we had one
        if (tagType != null)
            resolvedTags.add(new Tag(tagType, tagText));

        for (Tag tag : resolvedTags) {
            switch (tag.getType().toLowerCase().trim()) {
                case "param" :
                    int nextSpace = tag.getText().indexOf(' ');
                    if (nextSpace == -1)
                        parameters.put(tag.getText(), "");
                    else
                        parameters.put(tag.getText().substring(0, nextSpace),
                                tag.getText().substring(nextSpace + 1));
                    break;
                case "return" :
                    this.returns = tag.getText();
                    break;
                case "author" :
                case "author(s)" :
                    this.author = tag.getText();
                    break;
                case "deprecated" :
                    nextSpace = tag.getText().indexOf(' ');
                    if (nextSpace == -1)
                        deprecated = new Deprecated(tag.getText(), "");
                    else
                        deprecated = new Deprecated(tag.getText().substring(0, nextSpace),
                                tag.getText().substring(nextSpace + 1));
                    break;
                case "internal" :
                    this.isInternal = true;
                    break;
                default :
                    if (!"".equals(tag.getText().trim().replace("\n", "")))
                        this.comment += "### " + tag.getType() + ":\n" + tag.getText() + "\n";
                    break;
            }
        }
    }

    private void parseJavadocComment(String comment) {
        // convert crlf to lf to avoid eol problems
        comment = comment.replace("\r\n", "\n");

        String[] commentLines = comment.split("\n");

        String tagType = null;
        String tagText = null;
        List resolvedTags = new ArrayList<>();

        // Assuming the first and last lines are /** */
        for (int i = 1; i < commentLines.length - 1; i++) {

            // Lets get the line and trim off the leading *
            String commentLine = commentLines[i] + '\n'; // Put this back as we split on it
            commentLine = commentLine.substring(commentLine.indexOf('*') + 1);

            // There might be a space after the *, or not
            if (commentLine.length() > 0 && " ".equals(commentLine.substring(0, 1)))
                commentLine = commentLine.substring(1);

            // Assuming a line that starts with an @xxx is a token
            if (commentLine.startsWith("@") && !" ".equals(commentLine.substring(1, 2))) {

                // Store previous tag if we had one
                if (tagType != null)
                    resolvedTags.add(new Tag(tagType, tagText));

                Integer nextSpace = commentLine.indexOf(' ');

                if (nextSpace != -1) {
                    tagType = commentLine.substring(1, nextSpace);
                    tagText = ltrim(commentLine.substring(nextSpace));
                } else {
                    tagType = commentLine.substring(1);
                    tagText = "";
                }

                continue;
            }

            if (tagType != null)
                tagText += " " + commentLine;
            else
                this.comment += commentLine;

        }

        // Store previous tag if we had one
        if (tagType != null)
            resolvedTags.add(new Tag(tagType, tagText));

        int nextSpace;
        for (Tag tag : resolvedTags) {
            switch (tag.getType().trim()) {
                case "param" :
                    nextSpace = tag.getText().indexOf(' ');
                    if (nextSpace == -1)
                        parameters.put(tag.getText(), "");
                    else
                        parameters.put(tag.getText().substring(0, nextSpace),
                                tag.getText().substring(nextSpace + 1));
                    break;
                case "deprecated" :
                    nextSpace = tag.getText().indexOf(' ');
                    if (nextSpace == -1)
                        deprecated = new Deprecated(tag.getText(), "");
                    else
                        deprecated = new Deprecated(tag.getText().substring(0, nextSpace),
                                tag.getText().substring(nextSpace + 1));
                    break;
                case "return" :
                    this.returns = tag.getText();
                    break;
                case "author" :
                    this.author = tag.getText();
                    break;
                case "internal" :
                    this.isInternal = true;
                    break;
            }
        }
    }
    public String ltrim(String s, Character pChar) {
        int i = 0;
        while (i < s.length() && s.charAt(i) == pChar) {
            i++;
        }
        return s.substring(i);
    }

    public String rtrim(String s, Character pChar) {
        int i = s.length() - 1;
        while (i >= 0 && s.charAt(i) == pChar) {
            i--;
        }
        return s.substring(0, i + 1);
    }

    /**
     * Remove ABL comment characters
     * 
     * @param comment
     * @return
     */
    private String cleanAblComment(String comment) {
        /* Left */
        comment = ltrim(comment, '/');
        comment = ltrim(comment, '*');
        comment = ltrim(comment, '-');
        /* Right */
        comment = rtrim(comment, '\n');
        comment = rtrim(comment, '/');
        comment = rtrim(comment, '*');
        comment = rtrim(comment, '-');

        return comment;
    }

    private String ltrim(String s) {
        int i = 0;
        while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
            i++;
        }
        return s.substring(i);
    }

    public String markdown(String comment) {
        String markdown = "";

        Parser parser = Parser.builder().build();
        Node document = parser.parse(comment);
        HtmlRenderer renderer = HtmlRenderer.builder().build();
        markdown = renderer.render(document);

        return markdown;
    }

    private class Tag {
        private String type;
        private String text;

        public Tag(String type, String text) {
            // Trim the lasts lf char or lf space lf group
            this.type = type;
            this.text = cleanText(text);
        }

        public String getType() {
            return this.type;
        }

        public String getText() {
            return this.text;
        }

        /**
         * Remove useless EOL and Whitespaces
         */
        private String cleanText(String pText) {
            int i = pText.length() - 1;
            while (i >= 0 && (Character.isWhitespace(pText.charAt(i)) || pText.charAt(i) == '\n')) {
                i--;
            }
            return pText.substring(0, i + 1);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy