001/*
002 * JDrupes MDoclet
003 * Copyright 2013 Raffael Herzog
004 * Copyright (C) 2017 Michael N. Lipp
005 * 
006 * This program is free software; you can redistribute it and/or modify it 
007 * under the terms of the GNU General Public License as published by 
008 * the Free Software Foundation; either version 3 of the License, or 
009 * (at your option) any later version.
010 * 
011 * This program is distributed in the hope that it will be useful, but 
012 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
013 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
014 * for more details.
015 * 
016 * You should have received a copy of the GNU General Public License along 
017 * with this program; if not, see <http://www.gnu.org/licenses/>.
018 */
019package org.jdrupes.mdoclet;
020
021import java.util.HashMap;
022import java.util.List;
023import java.util.Map;
024import java.util.regex.Matcher;
025import java.util.regex.Pattern;
026
027/**
028 * Utility class providing some helpers for working with tags.
029 */
030public final class Tags {
031
032    /**
033     * The name of text tags in the resulting array of
034     * {@link com.sun.javadoc.Doc#inlineTags() Doc.inlineTags()}.
035     */
036    public static final String TEXT_TAG_NAME = "Text";
037
038    private static final Pattern TAG_RE = Pattern.compile("\\{@[^\\}]*\\}");
039    private static final Pattern SUBST_RE = Pattern.compile("\\{@\\}");
040
041    private static Map<String, String> KINDS = new HashMap<>();
042    {   
043        KINDS.put("@exception", "@throws");
044        KINDS.put("@link", "@see");
045        KINDS.put("@linkplain", "@see");
046        KINDS.put("@serialData", "@serial");
047    }
048
049    private Tags() {
050    }
051
052    /**
053     * Gets the {@link com.sun.javadoc.Tag#kind() kind} of the tag with the given name.
054     * Returns the original name if the tag is unknown.
055     *
056     * @param name    The tag's name.
057     *
058     * @return The kind of the tag.
059     *
060     * @see com.sun.javadoc.Tag#kind()
061     */
062    public static String kindOf(String name) {
063        String kind = KINDS.get(name);
064        return kind == null ? name : kind;
065    }
066
067    /**
068     * Extracts all inline tags from the given comment and saves them in a target list.
069     *
070     * **Example**
071     *
072     * ```
073     * /**
074     *  * Foo {{@literal @}link bar} bar.
075     *  *{@literal /}
076     * ```
077     *
078     * becomes
079     *
080     * ```
081     * /**
082     *  * Foo {{@literal @}} bar.
083     *  *{@literal /}
084     * ```
085     *
086     * and the target list contains the string `"{{@literal @}link bar}"`.
087     *
088     * @param comment    The comment to extract the inline tags from.
089     * @param target     The target list to save the extracted inline tags to.
090     *
091     * @return The comment with all inline tags replaced with `"{{@literal @}}"`.
092     *
093     * @see #insertInlineTags(String, java.util.List)
094     */
095    public static String extractInlineTags(String comment, List<String> target) {
096        StringBuffer result = new StringBuffer();
097        Matcher matcher = TAG_RE.matcher(comment);
098        while ( matcher.find() ) {
099            target.add(matcher.group());
100            matcher.appendReplacement(result, "{@}");
101        }
102        matcher.appendTail(result);
103        return result.toString();
104    }
105
106    /**
107     * Re-inserts all inline tags previously extracted using
108     * {@link #extractInlineTags(String, java.util.List) extractInlineTags()}. All
109     * occurrences of `"{{@literal @}}"` will be replaced by the string at the
110     * corresponding index of the list.
111     *
112     * @param comment    The comment text.
113     * @param tags       The list of saved inline tags.
114     *
115     * @return The String with all inline tags re-inserted.
116     *
117     * @see #extractInlineTags(String, java.util.List)
118     */
119    public static String insertInlineTags(String comment, List<String> tags) {
120        StringBuffer result = new StringBuffer();
121        Matcher matcher = SUBST_RE.matcher(comment);
122        int index = 0;
123        while ( matcher.find() ) {
124            String tag;
125            if ( index < tags.size() ) {
126                tag = tags.get(index++);
127            }
128            else {
129                tag = "{@}";
130            }
131            matcher.appendReplacement(result, Matcher.quoteReplacement(tag));
132        }
133        matcher.appendTail(result);
134        return result.toString();
135    }
136
137}