/* * Copyright (c) 2011-2012 Lockheed Martin Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.eurekastreams.server.action.execution.notification.notifier; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.text.StrLookup; import org.apache.commons.lang.text.StrSubstitutor; import org.apache.velocity.context.Context; import org.eurekastreams.server.domain.stream.ActivityDTO; /** * Class which provides helper routines for building notification messages. */ public class NotificationMessageBuilderHelper { /** Eureka variable start marker. */ private static final String VARIABLE_START_MARKER = "%EUREKA:"; /** Eureka variable end marker. */ private static final String VARIABLE_END_MARKER = "%"; /** Regex for extracting markdown links. */ private static final String MARKDOWN_LINK_REGEX = "\\[([^\\]\\[]+)\\]\\(([^()]+)\\)"; // TODO: Need better markdown conversion /** Compiled regex for extracting markdown links. */ private static final Pattern MARKDOWN_LINK_PATTERN = Pattern .compile(MARKDOWN_LINK_REGEX, Pattern.CASE_INSENSITIVE); /** Base URL to prepend to relative URLs. */ private final String baseUrl; /** * Constructor. * * @param inBaseUrl * Base URL to prepend to relative URLs. */ public NotificationMessageBuilderHelper(final String inBaseUrl) { baseUrl = inBaseUrl; } /** * Returns a variable-substituted version of the activity's body. * * @param activity * Activity. * @param context * Velocity context. * @return Activity body text. */ public String resolveActivityBody(final ActivityDTO activity, final Context context) { // substitute variables StrSubstitutor transform = new StrSubstitutor(new StrLookup() { @Override public String lookup(final String variableName) { if ("ACTORNAME".equals(variableName)) { return activity.getActor().getDisplayName(); } else { return null; } } }, VARIABLE_START_MARKER, VARIABLE_END_MARKER, StrSubstitutor.DEFAULT_ESCAPE); String result = transform.replace(activity.getBaseObjectProperties().get("content")); // if (!result.isEmpty()) { int startIndex = 0, lastSeenLinebreakInLeadingWhitespace = -1, endIndex = result.length(); while (startIndex < endIndex) { char c = result.charAt(startIndex); if (!Character.isWhitespace(c)) { break; } if (c != '\t' && Character.getType(c) == Character.CONTROL) { lastSeenLinebreakInLeadingWhitespace = startIndex; } startIndex++; } startIndex = lastSeenLinebreakInLeadingWhitespace + 1; while (startIndex < endIndex && Character.isWhitespace(result.charAt(endIndex - 1))) { endIndex--; } result = result.substring(startIndex, endIndex); } return result; } /** * Strip leading newlines and trailing whitespace and newlines. * * @param input * String to clean. * @return Cleaned string. */ public String cleanWhitespace(final String input) { if (input.isEmpty()) { return input; } int startIndex = 0, lastSeenLinebreakInLeadingWhitespace = -1, endIndex = input.length(); while (startIndex < endIndex) { char c = input.charAt(startIndex); if (!Character.isWhitespace(c)) { break; } if (c != '\t' && Character.getType(c) == Character.CONTROL) { lastSeenLinebreakInLeadingWhitespace = startIndex; } startIndex++; } startIndex = lastSeenLinebreakInLeadingWhitespace + 1; while (startIndex < endIndex && Character.isWhitespace(input.charAt(endIndex - 1))) { endIndex--; } return input.substring(startIndex, endIndex); } /** * Resolves the subset of markdown supported by Eureka into appropriate text. * * @param input * String potentially with markdown. * @return String with markdown replaced. */ public String resolveMarkdownForText(final String input) { Matcher matcher = MARKDOWN_LINK_PATTERN.matcher(input); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, ""); // use empty string here since it treats $ and \ specially String text = matcher.group(1); String url = matcher.group(2); if (url.charAt(0) == '#') { url = baseUrl + url; } sb.append(text).append(" (").append(url).append(")"); } if (sb.length() > 0) { matcher.appendTail(sb); return sb.toString(); } else { return input; } } /** * Resolves the subset of markdown supported by Eureka into appropriate text and HTML-escapes all input. * * @param input * String potentially with markdown. * @return String with markdown replaced. */ public String resolveMarkdownForHtml(final String input) { Matcher matcher = MARKDOWN_LINK_PATTERN.matcher(input); StringBuffer sb = new StringBuffer(); int copyFrom = 0; while (matcher.find()) { sb.append(StringEscapeUtils.escapeHtml(input.substring(copyFrom, matcher.start()))); copyFrom = matcher.end(); String text = matcher.group(1); String url = matcher.group(2); if (url.charAt(0) == '#') { url = baseUrl + url; } sb.append("<a href=\"").append(StringEscapeUtils.escapeHtml(url)).append("\">") .append(StringEscapeUtils.escapeHtml(text)).append("</a>"); } if (copyFrom > 0) { sb.append(StringEscapeUtils.escapeHtml(input.substring(copyFrom, input.length()))); return sb.toString(); } else { return StringEscapeUtils.escapeHtml(input); } } }