org.richfaces.convert.TreeConverterUtil Maven / Gradle / Ivy
The newest version!
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.richfaces.convert;
import java.text.MessageFormat;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
/**
* @author Nick Belaevski
*
*/
public final class TreeConverterUtil {
private static final class SeparatorCharHolder {
static final char SEPARATOR_CHAR = UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance());
private SeparatorCharHolder() {
}
}
private static final char ESCAPE_CHAR = '_';
private TreeConverterUtil() {
}
private static boolean shouldEscape(char c) {
if ('a' <= c && c <= 'z') {
return false;
}
if ('A' <= c && c <= 'Z') {
return false;
}
if ('0' <= c && c <= '9') {
return false;
}
if (c == ESCAPE_CHAR || c == SeparatorCharHolder.SEPARATOR_CHAR) {
return true;
}
if ('-' == c || '\u00B7' == c) {
return false;
}
if ('\u00C0' <= c && c <= '\u00D6') {
return false;
}
if ('\u00D8' <= c && c <= '\u00F6') {
return false;
}
if ('\u00F8' <= c && c <= '\u02FF') {
return false;
}
if ('\u0370' <= c && c <= '\u037D') {
return false;
}
if ('\u037F' <= c && c <= '\u1FFF') {
return false;
}
if ('\u200C' <= c && c <= '\u200D') {
return false;
}
if ('\u2070' <= c && c <= '\u218F') {
return false;
}
if ('\u2C00' <= c && c <= '\u2FEF') {
return false;
}
if ('\u3001' <= c && c <= '\uD7FF') {
return false;
}
if ('\uF900' <= c && c <= '\uFDCF') {
return false;
}
if ('\uFDF0' <= c && c <= '\uFFFD') {
return false;
}
if ('\u0300' <= c && c <= '\u036F') {
return false;
}
if ('\u203F' <= c && c <= '\u2040') {
return false;
}
return true;
}
private static int parseHexString(String s) {
int result = 0;
for (int i = 0; i < s.length(); i++) {
result <<= 4;
char c = s.charAt(i);
int digitValue = Character.digit(c, 16);
if (digitValue < 0) {
throw new NumberFormatException();
}
result += digitValue;
}
return result;
}
private static void checkAvailable(String s, int idx, int len) {
if (s.length() < idx + len) {
throw new IllegalArgumentException(MessageFormat.format(
"Expected {0} available chars in ''{1}'' string starting from {2} index", len, s, idx));
}
}
private static char getNextChar(String s, int idx) {
checkAvailable(s, idx, 1);
return s.charAt(idx);
}
private static char readNextCharFromHexCode(String s, int idx, int len) {
checkAvailable(s, idx, len);
String numString = s.substring(idx, idx + len);
try {
int charValue = parseHexString(numString);
return (char) charValue;
} catch (NumberFormatException e) {
throw new IllegalArgumentException(MessageFormat.format(
"Substring ''{0}'' of ''{1}'' string is not a valid hex number ", numString, s));
}
}
public static String unescape(String s) {
StringBuilder sb = new StringBuilder(s.length());
int startIdx = 0;
while (startIdx >= 0) {
int idx = s.indexOf(ESCAPE_CHAR, startIdx);
if (idx >= 0) {
sb.append(s.subSequence(startIdx, idx));
idx++; // skip escape char
char c = getNextChar(s, idx);
switch (c) {
case ESCAPE_CHAR:
idx++;
sb.append(c);
break;
case 'x':
idx++;
sb.append(readNextCharFromHexCode(s, idx, 2));
idx += 2;
break;
case 'u':
idx++;
sb.append(readNextCharFromHexCode(s, idx, 4));
idx += 4;
break;
default:
throw new IllegalArgumentException(MessageFormat.format(
"Unexpected char ''{0}'' in ''{1}'' string located at index {2}", c, s, idx));
}
} else {
sb.append(s.subSequence(startIdx, s.length()));
}
startIdx = idx;
}
return sb.toString();
}
public static String escape(String s) {
StringBuilder sb = new StringBuilder(s.length());
int start = 0;
char[] cs = s.toCharArray();
for (int idx = 0; idx < cs.length; idx++) {
char c = cs[idx];
if (shouldEscape(c)) {
sb.append(cs, start, idx - start);
sb.append(ESCAPE_CHAR);
if (c == ESCAPE_CHAR) {
sb.append(c); // ${escapeChar}
} else {
String asHex = Integer.toHexString(c);
switch (asHex.length()) {
case 1:
sb.append("x0"); // _x05
break;
case 2:
sb.append("x"); // _xef
break;
case 3:
sb.append("u0"); // _u0fed
break;
case 4:
sb.append("u"); // _ufcda
break;
default:
throw new IllegalArgumentException();
}
sb.append(asHex);
}
start = idx + 1;
}
}
if (start < s.length()) {
sb.append(cs, start, s.length() - start);
}
return sb.toString();
}
}