/*
* 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.processor.xhtml;
import org.fourthline.lemma.processor.ProcessorOptions;
import org.seamless.xhtml.XHTML;
import org.seamless.xhtml.XHTMLElement;
import org.fourthline.lemma.Constants;
import org.fourthline.lemma.pipeline.Context;
import org.fourthline.lemma.anchor.CitationAnchor;
import org.fourthline.lemma.anchor.AnchorAddress;
import org.fourthline.lemma.anchor.Scheme;
import org.fourthline.lemma.processor.AbstractProcessor;
import java.util.logging.Logger;
/**
* Detects cross-reference anchors and sets their link text.
*
* @author Christian Bauer
*/
public class XRefProcessor extends AbstractProcessor<XHTML, XHTML> {
private Logger log = Logger.getLogger(XRefProcessor.class.getName());
public XHTML process(XHTML input, Context context) {
log.fine("Processing input...");
ProcessorOptions processorOptions = (ProcessorOptions)context.get(ProcessorOptions.CONTEXT_PROCESSOR_OPTIONS);
if (!processorOptions.processXRefs)
return input;
XHTML output = transformReferences(input, context);
/*
if (log.isLoggable(Level.FINEST)) {
log.finest("Completed processing input, generated output: ");
log.finest("--------------------------------------------------------------------------------");
log.finest(XML.toString(output, false));
log.finest("--------------------------------------------------------------------------------");
}
*/
return output;
}
protected XHTML transformReferences(XHTML input, Context context) {
CitationAnchor[] xrefs = CitationAnchor.findCitationAnchors(getXPath(), input, Constants.TYPE_XREF);
for (CitationAnchor xref : xrefs) {
String xrefTarget = xref.getAddress().toIdentifierString();
// We have to try both schemes because {@link} just specifies the class/method and not the scheme
String javacodeXrefTargetIdentifier =
new AnchorAddress(
Scheme.JAVACODE,
xref.getAddress().getPath(),
xref.getAddress().getFragment()
).toIdentifierString();
log.finest("Trying to resolve xref: " + xrefTarget);
XHTMLElement resolvedCitationElement = input.getRoot(getXPath()).findChildWithIdentifier(xrefTarget);
if (resolvedCitationElement == null) {
log.fine("Could not resolve xref, trying: " + javacodeXrefTargetIdentifier);
resolvedCitationElement = input.getRoot(getXPath()).findChildWithIdentifier(javacodeXrefTargetIdentifier);
}
if (resolvedCitationElement != null) {
// Set new address (HREF) on xref element
xref.setAttribute(XHTML.ATTR.href, "#" + resolvedCitationElement.getId());
// If it doesn't have a label, set a label
if (!xref.getW3CElement().hasChildNodes()) {
String citationLabel = getResolvedLabel(xref, resolvedCitationElement);
xref.setContent(citationLabel != null ? citationLabel : getResolvedLabel(xref));
}
} else {
log.warning("Linked citation identifier not found: " + xrefTarget + "/" + javacodeXrefTargetIdentifier);
// Clean up and set a message that makes unresolved links easy to see
xref.removeChildren();
xref.setAttribute(XHTML.ATTR.href, getUnresolvedLink(xrefTarget))
.setAttribute(XHTML.ATTR.CLASS, Constants.TYPE_XREF + " " + Constants.TYPE_UNRESOLVED)
.setContent(getUnresolvedLabel(xrefTarget));
}
}
return input;
}
protected String getResolvedLabel(CitationAnchor xref) {
return "(LINK)";
}
protected String getResolvedLabel(CitationAnchor xref, XHTMLElement citationElement) {
// Try to find a direct child element that is a 'title' class, then take that content as label
XHTMLElement[] children = citationElement.getChildren();
for (XHTMLElement child : children) {
String[] types = child.getClasses();
for (String t : types) {
if (t.trim().equals(Constants.TYPE_TITLE)) {
String title = child.getContent();
// TODO: And cut off that last period of the 'first sentence' title
return title.endsWith(".") ? title.substring(0, title.length() - 1) : title;
}
}
}
return null;
}
protected String getUnresolvedLink(String xrefTarget) {
return "#UNRESOLVED_LINK";
}
protected String getUnresolvedLabel(String xrefTarget) {
return "UNRESOLVED ID: " + xrefTarget;
}
}