package com.door43.translationstudio.rendering;
import android.text.TextUtils;
import com.door43.translationstudio.spannables.ArticleLinkSpan;
import com.door43.translationstudio.spannables.PassageLinkSpan;
import com.door43.translationstudio.spannables.Span;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This is the link rendering engine.
*/
public class LinkRenderer extends RenderingEngine {
private final Span.OnClickListener mLinkListener;
private final OnPreprocessLink preprocessCallback;
private boolean renderHtml = false;
/**
* Creates a new link rendering engine with some custom click listeners
* @param linkListener
*/
public LinkRenderer(OnPreprocessLink preprocessor, Span.OnClickListener linkListener) {
mLinkListener = linkListener;
preprocessCallback = preprocessor;
}
@Override
public CharSequence render(CharSequence in) {
this.renderHtml = false;
CharSequence out = in;
out = renderPassageLink(out);
out = renderTranslationAcademyLink(out);
return out;
}
public String renderHtml(CharSequence in) {
this.renderHtml = true;
CharSequence out = in;
out = renderPassageLink(out);
out = renderTranslationAcademyLink(out);
return out.toString();
}
/**
* Renders links to other passages
* @param in
* @return
*/
private CharSequence renderPassageLink(CharSequence in) {
return renderLink(in, PassageLinkSpan.PATTERN, new OnCreateLink() {
@Override
public Span onCreate(Matcher matcher) {
return new PassageLinkSpan(matcher.group(3), matcher.group(2));
}
});
}
/**
* Renders links to translation academy pages
* @param in
* @return
*/
private CharSequence renderTranslationAcademyLink(CharSequence in) {
return renderLink(in, ArticleLinkSpan.ADDRESS_PATTERN, new OnCreateLink() {
@Override
public Span onCreate(Matcher matcher) {
return ArticleLinkSpan.parse(matcher.group(3), matcher.group(2));
}
});
}
/**
* A generic rendering method for rendering span links
*
* @param in
* @param pattern
* @param callback
* @return
*/
private CharSequence renderLink(CharSequence in, Pattern pattern, OnCreateLink callback) {
CharSequence out = "";
Matcher matcher = pattern.matcher(in);
int lastIndex = 0;
while(matcher.find()) {
if(isStopped()) return in;
Span link = callback.onCreate(matcher);
if(link != null) {
link.setOnClickListener(mLinkListener);
if (preprocessCallback == null || preprocessCallback.onPreprocess(link)) {
// render clickable link
if(this.renderHtml) {
String htmlLink = "<app-link href=\"" + link.getMachineReadable() + "\">" + link.getHumanReadable() + "</app-link>";
out = TextUtils.concat(out, in.subSequence(lastIndex, matcher.start()), htmlLink);
} else {
out = TextUtils.concat(out, in.subSequence(lastIndex, matcher.start()), link.toCharSequence());
}
} else {
// render non-clickable link
out = TextUtils.concat(out, in.subSequence(lastIndex, matcher.start()), link.getHumanReadable());
}
} else {
// ignore link
out = TextUtils.concat(out, in.subSequence(lastIndex, matcher.end()));
}
lastIndex = matcher.end();
}
out = TextUtils.concat(out, in.subSequence(lastIndex, in.length()));
return out;
}
private interface OnCreateLink {
Span onCreate(Matcher matcher);
}
/**
* Used to identify which links to render
*/
public interface OnPreprocessLink {
boolean onPreprocess(Span span);
}
}