/* * Tweetings - Twitter client for Android * * Copyright (C) 2012-2013 RBD Solutions Limited <apps@tweetings.net> * Copyright (C) 2012 Mariotaku Lee <mariotaku.lee@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.dwdesign.tweetings.util; import static com.dwdesign.tweetings.util.HtmlEscapeHelper.escape; import static com.dwdesign.tweetings.util.HtmlEscapeHelper.unescape; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class HtmlBuilder { private final String string; private final int string_length; private final boolean strict; private final List<LinkSpec> links = new ArrayList<LinkSpec>(); public HtmlBuilder(final String string) { this(string, false); } public HtmlBuilder(final String string, final boolean strict) { if (string == null) throw new NullPointerException(); this.string = string; this.strict = strict; string_length = string.length(); } public boolean addLink(final String link, final String display, final int start, final int end) { // if (start >= end) { // if (strict) throw new // IllegalArgumentException("start must lesser than end!"); // return; // } if (start < 0 || end < 0 || start > end || end > string_length) { if (strict) throw new StringIndexOutOfBoundsException("String length = " + string_length + ", start = " + start + ", end = " + end); return false; } for (final LinkSpec spec : links) { if (start >= spec.start && start <= spec.end || end >= spec.start && end <= spec.end) { if (strict) throw new IllegalArgumentException("link already added in this range!"); return false; } } return links.add(new LinkSpec(link, display, start, end)); } public String build(final boolean unescape) { if (links.size() == 0) return escape(unescape ? unescape(string) : string); Collections.sort(links, LinkSpec.COMPARATOR); final StringBuilder builder = new StringBuilder(); final int links_size = links.size(); for (int i = 0; i < links_size; i++) { final LinkSpec spec = links.get(i); if (spec == null) { continue; } final int start = spec.start, end = spec.end; if (i == 0) { if (start >= 0 && start <= string_length) { builder.append(escape(unescape ? unescape(string.substring(0, start)) : string.substring(0, start))); } } else if (i > 0) { final int last_end = links.get(i - 1).end; if (last_end >= 0 && last_end <= start && start <= string_length) { builder.append(escape(unescape ? unescape(string.substring(last_end, start)) : string.substring( last_end, start))); } } builder.append("<a href=\"" + spec.link + "\">"); if (start >= 0 && start <= end && end <= string_length) { builder.append(spec.display != null ? spec.display : escape(unescape ? unescape(string.substring(start, end)) : string.substring(start, end))); } builder.append("</a>"); if (i == links.size() - 1 && end >= 0 && end <= string_length) { builder.append(escape(unescape ? unescape(string.substring(end, string_length)) : string.substring(end, string_length))); } } return builder.toString(); } static class LinkSpec { private static final Comparator<LinkSpec> COMPARATOR = new Comparator<LinkSpec>() { @Override public int compare(final LinkSpec lhs, final LinkSpec rhs) { return lhs.start - rhs.start; } }; final String link, display; final int start, end; LinkSpec(final String link, final String display, final int start, final int end) { this.link = link; this.display = display; this.start = start; this.end = end; } @Override public String toString() { return "LinkSpec(" + link + ", " + start + ", " + end + ")"; } } }