/*
* Copyright 2009 Toby Speight
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
package uk.me.parabola.mkgmap.osmstyle.actions;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import uk.me.parabola.mkgmap.reader.osm.Element;
/**
* Prepend a Garmin magic-character to the value.
*
* @author Toby Speight
*/
public class HighwaySymbolFilter
extends ValueFilter
{
private final String prefix
;
private static final Map<String,
String> symbols =
new HashMap<>();
private static final int MAX_REF_LENGTH =
8; // enough for "A6144(M)" (RIP)
private int maxAlphaNum = MAX_REF_LENGTH
; // Max. length for alphanumeric (e.g., 'A67')
private int maxAlpha = MAX_REF_LENGTH
; // Max. length for alpha only signs (e.g., 'QEW')
private static final Pattern spacePattern =
Pattern.
compile(" ",
Pattern.
LITERAL);
private static final Pattern semicolonPattern =
Pattern.
compile(";",
Pattern.
LITERAL);
static {
symbols.
put("interstate",
"\u0001"); // US Interstate
symbols.
put("shield",
"\u0002"); // US Highway shield
symbols.
put("round",
"\u0003"); // US Highway round
symbols.
put("hbox",
"\u0004"); // box with horizontal bands
symbols.
put("box",
"\u0005"); // Square box
symbols.
put("oval",
"\u0006"); // box with rounded ends
}
public HighwaySymbolFilter
(String s
) {
String[] filters = s.
split(":");
// First, try the lookup table
String p = symbols.
get(filters
[0]);
if (p ==
null) {
p =
"[" + filters
[0] +
"]";
}
prefix = p
;
// Set maximum length for alpha/alphanumeric signs:
if ( filters.
length ==
3 ) {
maxAlphaNum =
Integer.
parseInt(filters
[1]);
maxAlpha =
Integer.
parseInt(filters
[2]);
} else if ( filters.
length ==
2 ) {
maxAlphaNum =
Integer.
parseInt(filters
[1]);
maxAlpha = maxAlphaNum
; // If only one option specified, use for both
} else {
maxAlphaNum = MAX_REF_LENGTH
; // Ensure use of defaults if none specified
maxAlpha = MAX_REF_LENGTH
;
}
}
public String doFilter
(String value,
Element el
) {
if (value ==
null) return value
;
// Nuke all spaces
String shieldText = spacePattern.
matcher(value
).
replaceAll(Matcher.
quoteReplacement(""));
// Also replace ";" with "/", to change B3;B4 to B3/B4
shieldText = semicolonPattern.
matcher(shieldText
).
replaceAll(Matcher.
quoteReplacement("/"));
// Check if value is alphanumeric
boolean isAlphaNum =
false;
for (char c : shieldText.
toCharArray()) {
if (Character.
isDigit(c
)) {
isAlphaNum =
true; // Consider alphanumeric if we find one or more digits
break;
}
}
// Check if shield exceeds maximum length:
int codePointLength = shieldText.
codePointCount(0, shieldText.
length());
if (isAlphaNum
&& codePointLength
> maxAlphaNum ||
!isAlphaNum
&& codePointLength
> maxAlpha
) {
// ??? this doesn't do as described in the documentation
return value
; // If so, return original value
} else {
return prefix + shieldText
; // If not, return condensed value with magic code
}
}
}