/*
* Copyright 2014 Skynav, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY SKYNAV, INC. AND ITS CONTRIBUTORS “AS IS” AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL SKYNAV, INC. OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.skynav.ttv.util;
import java.util.ResourceBundle;
import org.xml.sax.Locator;
import com.skynav.xml.helpers.XML;
public class LocatedMessage extends Message {
public static final int LINE_CONTEXT_COUNT = 3;
private String uri;
private int row = -1;
private int col = -1;
private String[] lines;
private int linesRowOffset = -1;
public LocatedMessage(Locator locator, String key, String format, Object... arguments) {
this(locator.getSystemId(), locator.getLineNumber(), locator.getColumnNumber(), null, key, format, arguments);
}
public LocatedMessage(String uri, int row, int col, String[] resourceLines, String key, String format, Object... arguments) {
super(key, format, arguments);
this.uri = uri;
this.row = row;
this.col = col;
if ((resourceLines != null) && (row > 0))
populateLines(resourceLines, row, LINE_CONTEXT_COUNT);
}
private void populateLines(String[] resourceLines, int row, int lineContextCount) {
assert row > 0;
int lineNumber = row - 1;
if (lineNumber >= resourceLines.length)
lineNumber = resourceLines.length - 1;
int lineBeforeCount = (lineContextCount - 1) / 2;
int lineAfterCount = (lineContextCount - 1) / 2;
if (lineBeforeCount < 1)
lineBeforeCount = 1;
if (lineAfterCount < 1)
lineAfterCount = 1;
int lineBeforeCountAvailable = lineNumber;
if (lineBeforeCountAvailable < lineBeforeCount)
lineBeforeCount = lineBeforeCountAvailable;
int lineAfterCountAvailable = resourceLines.length - (lineNumber + 1);
if (lineAfterCountAvailable < lineAfterCount)
lineAfterCount = lineAfterCountAvailable;
int lineCount = lineBeforeCount + 1 + lineAfterCount;
String[] lines = new String[lineCount];
int firstLineOffset = lineNumber - lineBeforeCount;
for (int i = firstLineOffset, n = i + lineCount; i < n; ++i) {
lines[i - firstLineOffset] = resourceLines[i];
}
this.lines = lines;
this.linesRowOffset = firstLineOffset + 1;
}
@Override
public String toText(ResourceBundle bundle, boolean hideLocation, boolean hidePath) {
String text = super.toText(bundle, false, false);
if (uri != null) {
StringBuffer sb = new StringBuffer();
if (!hideLocation) {
sb.append('{');
String uriString = uri;
if (hidePath)
uriString = hidePath(uriString);
sb.append(uriString);
sb.append('}');
}
if (row >= 0) {
if (sb.length() > 0)
sb.append(':');
sb.append('[');
sb.append(row);
if (col >= 0) {
sb.append(',');
sb.append(col);
}
sb.append(']');
}
if (sb.length() > 0)
sb.append(':');
sb.append(text);
text = sb.toString();
}
return text;
}
public String toXML(ResourceBundle bundle, boolean hideLocation, boolean hidePath, boolean showSource) {
StringBuffer sb = new StringBuffer();
sb.append("<message>\n");
sb.append(toXMLLocation(hideLocation, hidePath));
sb.append(toXMLKey());
sb.append(toXMLText(bundle));
if (showSource)
sb.append(toXMLSource());
sb.append("</message>\n");
return sb.toString();
}
private String toXMLLocation(boolean hideLocation, boolean hidePath) {
StringBuffer sb = new StringBuffer();
if (uri != null) {
sb.append("<location>\n");
if (!hideLocation) {
sb.append("<url>");
String uriString = uri;
if (hidePath)
uriString = hidePath(uriString);
sb.append(escapeText(uriString));
sb.append("</url>\n");
}
if (row >= 0) {
sb.append("<row>");
sb.append(row);
sb.append("</row>\n");
if (col >= 0) {
sb.append("<col>");
sb.append(col);
sb.append("</col>\n");
}
}
sb.append("</location>\n");
}
return sb.toString();
}
private String toXMLSource() {
StringBuffer sb = new StringBuffer();
if (lines != null) {
sb.append("<source>\n");
int i = linesRowOffset;
for (String line : lines) {
int lineLength = line.length();
sb.append("<line row=\"");
sb.append(i);
sb.append("\">");
if (i == row) {
int j = col - 1;
if (j > lineLength - 1)
j = lineLength - 1;
String s1, s2, s3;
if (j > 0)
s1 = line.substring(0, j);
else
s1 = null;
if (j < line.length())
s2 = line.substring(j, j + 1);
else
s2 = null;
if (j + 1 < line.length())
s3 = line.substring(j + 1);
else
s3 = null;
if (s1 != null) {
sb.append("<unmarked>");
sb.append(XML.escapeMarkup(s1, true));
sb.append("</unmarked>");
}
if (s2 != null) {
sb.append("<marked>");
sb.append(XML.escapeMarkup(s2, true));
sb.append("</marked>");
}
if (s3 != null) {
sb.append("<unmarked>");
sb.append(XML.escapeMarkup(s3, true));
sb.append("</unmarked>");
}
} else {
sb.append("<unmarked>");
sb.append(XML.escapeMarkup(line, true));
sb.append("</unmarked>");
}
sb.append("</line>\n");
++i;
}
sb.append("</source>\n");
}
return sb.toString();
}
private String hidePath(String uriString) {
if (uriString != null) {
int index = uriString.lastIndexOf("/");
if (index >= 0)
uriString = uriString.substring(index + 1);
}
return uriString;
}
}