/*
* Copyright (C) 2011 4th Line GmbH, Switzerland
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fourthline.lemma.reader.javadoc;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.Doc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.PackageDoc;
import com.sun.javadoc.RootDoc;
import org.seamless.xhtml.XHTML;
import org.fourthline.lemma.Constants;
import org.fourthline.lemma.anchor.AnchorAddress;
import org.fourthline.lemma.anchor.CitationAnchor;
import org.fourthline.lemma.anchor.Scheme;
import org.fourthline.lemma.pipeline.Context;
import org.fourthline.lemma.reader.AbstractReader;
import java.util.logging.Logger;
/**
* Looks up the Javadoc <code>RootDoc</code> from the context.
*
* @author Christian Bauer
*/
public abstract class AbstractJavadocReader extends AbstractReader {
final private Logger log = Logger.getLogger(AbstractJavadocReader.class.getName());
final public static String CONTEXT_ROOT_DOC = "JavadocReader.rootDoc";
public XHTML read(CitationAnchor citation, Context context) {
RootDoc rootDoc = (RootDoc) context.get(CONTEXT_ROOT_DOC);
if (rootDoc == null) {
throw new IllegalStateException("Missing root Javadoc in context, can't read Javadoc");
}
return read(citation, context, rootDoc);
}
protected abstract XHTML read(CitationAnchor citation, Context context, RootDoc rootDoc);
protected Doc findTargetDoc(CitationAnchor citation, RootDoc rootDoc) {
if (!(citation.getAddress().getScheme().equals(Scheme.JAVADOC) ||
citation.getAddress().getScheme().equals(Scheme.JAVACODE))) {
throw new RuntimeException("TODO: NO SUPPORT FOR file://some/JavaClass.java ADDRESSES!");
}
// Try package name first
Doc targetDoc = rootDoc.packageNamed(citation.getAddress().getPath());
if (targetDoc == null) {
// Now try class name
targetDoc = rootDoc.classNamed(citation.getAddress().getPath());
// Get method doc for signature (both qualified and flat are attempted)
// TODO: This might not guarantee a hit because we only check qualified names syntactically, not semantically
String fragment = citation.getAddress().getFragment();
if (targetDoc != null && fragment != null) {
MethodDoc[] methodDocs = ((ClassDoc) targetDoc).methods();
targetDoc = null;
log.finest("Trying to find matching signature for citation target fragment: " + fragment);
for (MethodDoc methodDoc : methodDocs) {
String qualifiedSignature = methodDoc.name() + methodDoc.signature();
String unqualifiedSignature = methodDoc.name() + methodDoc.flatSignature();
if (qualifiedSignature.equals(fragment) || unqualifiedSignature.equals(fragment)) {
log.finest("Found method with matching signature: " + methodDoc.position());
targetDoc = methodDoc;
break;
}
}
}
}
if (targetDoc == null) {
throw new IllegalArgumentException("Target not found in Javadoc unit: " + citation);
}
return targetDoc;
}
protected XHTML resolveThisReferences(Context context, Doc targetDoc, XHTML input) {
CitationAnchor[] anchors = CitationAnchor.findCitationAnchors(getXPath(), input, Constants.TYPE_CITATION);
for (CitationAnchor citation : anchors) {
if (citation.getAddress().getPath().equals(AnchorAddress.PATH_THIS)) {
AnchorAddress resolvedAddress;
if (targetDoc instanceof ClassDoc) {
resolvedAddress = AnchorAddress.valueOf(
citation.getAddress().getScheme(),
(ClassDoc)targetDoc,
citation.getAddress().getFragment()
);
} else if (targetDoc instanceof PackageDoc) {
resolvedAddress = AnchorAddress.valueOf(
citation.getAddress().getScheme(),
(PackageDoc)targetDoc
);
} else if (targetDoc instanceof MethodDoc) {
resolvedAddress = AnchorAddress.valueOf(
citation.getAddress().getScheme(),
(MethodDoc)targetDoc
);
} else {
throw new IllegalArgumentException(
"Unknown doc type/reference, unable to resolve 'this' reference: " + citation
);
}
log.fine("Replacing 'this' reference with anchor address: " + resolvedAddress);
citation.setAttribute(XHTML.ATTR.href, resolvedAddress.toString());
}
}
return input;
}
}