/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2005-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.maven.taglet;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import com.sun.javadoc.Tag;
import com.sun.tools.doclets.Taglet;
/**
* The <code>@source</code> tag. This tag expects an URL to the source in the SVN repository.
* The SVN URL keyword is ignored.
*
* @source $URL$
* @version $Id$
* @author Martin Desruisseaux
*/
public final class Source implements Taglet {
/**
* Register this taglet.
*
* @param tagletMap the map to register this tag to.
*/
public static void register(final Map<String, Taglet> tagletMap) {
final Source tag = new Source();
tagletMap.put(tag.getName(), tag);
}
/**
* The delimiter for SVN keywords.
*/
static final char SVN_KEYWORD_DELIMITER = '$';
/**
* The base URL for Maven repository.
*/
public static final String SVN_REPO_URL = "http://svn.osgeo.org/geotools/";
/**
* The pattern to use for fetching the URL. The bit we want is in capture group 2
*/
final Pattern findURL = Pattern.compile(
"\\s*(\\" + SVN_KEYWORD_DELIMITER + "URL\\s*\\:)?\\s*(.+?)\\s*"
+ "(\\" + SVN_KEYWORD_DELIMITER + "\\s*)?");
static final int URL_CAPTURE_GROUP = 2;
/**
* The pattern to use for fetching the module name from an URL.
*/
final Pattern findModule;
/**
* Constructs a default <code>@source</code> taglet.
*/
Source() {
super();
findModule = Pattern.compile(
"https?\\Q://\\E" + // http or https
"[a-zA-Z\\.\\-]+" + // host e.g. svn.osgeo.org
"\\/geotools" + // /geotools
"\\/[a-z]+" + // trunk or tags or branches
"(\\/[a-zA-Z0-9\\-\\_\\.]+)?" + // group 1: tag or branch name or null if trunk
"\\/(((modules)\\/(library|plugin|extension|unsupported))|demo)" + // groups 2 - 5
"\\/(.+)" + // group 6: module name
"\\/src.*");
}
/**
* Returns the name of this custom tag.
*
* @return The tag name.
*/
public String getName() {
return "source";
}
/**
* Returns {@code true} since <code>@source</code> can be used in overview.
*
* @return Always {@code true}.
*/
public boolean inOverview() {
return true;
}
/**
* Returns {@code true} since <code>@source</code> can be used in package documentation.
*
* @return Always {@code true}.
*/
public boolean inPackage() {
return true;
}
/**
* Returns {@code true} since <code>@source</code> can be used in type documentation
* (classes or interfaces).
*
* @return Always {@code true}.
*/
public boolean inType() {
return true;
}
/**
* Returns {@code true} since <code>@source</code> can be used in constructor
*
* @return Always {@code true}.
*/
public boolean inConstructor() {
return true;
}
/**
* Returns {@code true} since <code>@source</code> can be used in method documentation.
*
* @return Always {@code true}.
*/
public boolean inMethod() {
return true;
}
/**
* Returns {@code true} since <code>@source</code> can be used in field documentation.
*
* @return Always {@code true}.
*/
public boolean inField() {
return true;
}
/**
* Returns {@code false} since <code>@source</code> is not an inline tag.
*
* @return Always {@code false}.
*/
public boolean isInlineTag() {
return false;
}
/**
* Given the <code>Tag</code> representation of this custom tag, return its string representation.
* The default implementation invokes the array variant of this method.
*
* @param tag The tag to format.
* @return A string representation of the given tag.
*/
public String toString(final Tag tag) {
return toString(new Tag[]{tag});
}
/**
* Given an array of {@code Tag}s representing this custom tag, return its string
* representation.
*
* @param tags The tags to format.
* @return A string representation of the given tags.
*/
public String toString(final Tag[] tags) {
// there should be a single tag
if (tags == null || tags.length != 1) {
return "";
}
StringBuilder sb = new StringBuilder();
sb.append("\n<DT><B>Module:</B></DT>");
String tagText = tags[0].text();
final Matcher matchURL = findURL.matcher(tagText);
if (!matchURL.matches()) {
return ""; // continue;
}
final String url = matchURL.group(URL_CAPTURE_GROUP).trim();
final Matcher matchModule = findModule.matcher(url);
if (!matchModule.matches()) {
return ""; // continue;
}
final String modulePath = matchModule.group(6);
int pos = modulePath.indexOf('/');
final String module;
if (pos == -1) {
module = modulePath;
} else {
module = modulePath.substring(pos + 1);
}
final String group, category;
if (matchModule.group(2).equals("demo")) {
group = matchModule.group(2);
category = null;
} else {
group = matchModule.group(4);
category = matchModule.group(5);
}
/*
* Module path e.g. modules/library/main
*/
sb.append("\n<DD><CODE><B>");
sb.append(group).append('/');
if (category != null) {
sb.append(category).append('/');
}
sb.append(module);
/*
* Jar name in brackets e.g. (gt-main.jar)
*/
sb.append(" (gt-").append(module).append(".jar)");
sb.append("</B></CODE>");
sb.append("</DD>\n");
sb.append("\n<DT><B>Source repository:</B></DT>").append('\n');
sb.append("<DD> <CODE>").append(url).append("</CODE></DD>\n");
return sb.toString();
}
}