You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@abdera.apache.org by jm...@apache.org on 2007/12/01 09:11:40 UTC
svn commit: r600056 - in /incubator/abdera/java/trunk/dependencies/i18n/src:
main/java/org/apache/abdera/i18n/io/ main/java/org/apache/abdera/i18n/iri/
main/java/org/apache/abdera/i18n/templates/
main/java/org/apache/abdera/i18n/unicode/ test/java/org/...
Author: jmsnell
Date: Sat Dec 1 00:11:39 2007
New Revision: 600056
URL: http://svn.apache.org/viewvc?rev=600056&view=rev
Log:
Variety of improvements including support for proper rendering of IRI Templates that contain bidi characters, better handling of escaped characters, additional escaping options, etc
Modified:
incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/io/CharUtils.java
incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/iri/Escaping.java
incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/HashMapContext.java
incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Operation.java
incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Template.java
incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/unicode/Normalizer.java
incubator/abdera/java/trunk/dependencies/i18n/src/test/java/org/apache/abdera/i18n/test/iri/TestTemplate.java
Modified: incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/io/CharUtils.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/io/CharUtils.java?rev=600056&r1=600055&r2=600056&view=diff
==============================================================================
--- incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/io/CharUtils.java (original)
+++ incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/io/CharUtils.java Sat Dec 1 00:11:39 2007
@@ -281,6 +281,10 @@
s = s.substring(0,s.length()-1);
return s;
}
+
+ public static String stripBidiInternal(String s) {
+ return s.replaceAll("[\u202A\u202B\u202D\u202E\u200E\u200F\u202C]", "");
+ }
/**
* Returns true if the character is a bidi control
Modified: incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/iri/Escaping.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/iri/Escaping.java?rev=600056&r1=600055&r2=600056&view=diff
==============================================================================
--- incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/iri/Escaping.java (original)
+++ incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/iri/Escaping.java Sat Dec 1 00:11:39 2007
@@ -18,9 +18,19 @@
package org.apache.abdera.i18n.iri;
import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.FilterWriter;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.nio.CharBuffer;
import org.apache.abdera.i18n.io.CharUtils;
import org.apache.abdera.i18n.io.CharUtils.Profile;
@@ -39,8 +49,13 @@
private Escaping() {}
private static void encode(Appendable sb, byte... bytes) {
+ encode(sb,0,bytes.length,bytes);
+ }
+
+ private static void encode(Appendable sb, int offset, int length, byte... bytes) {
try {
- for (byte c : bytes) {
+ for (int n = offset, i = 0; n < bytes.length && i < length; n++, i++) {
+ byte c = bytes[n];
sb.append("%");
sb.append(HEX[(c >> 4) & 0x0f]);
sb.append(HEX[(c >> 0) & 0x0f]);
@@ -50,15 +65,261 @@
}
}
- public static String encode(String s) {
+ public static String encode(char... chars) {
+ return encode(chars,0,chars.length,"UTF-8",new Profile[0]);
+ }
+
+ public static String encode(char[] chars, Profile profile) {
+ return encode(chars,0,chars.length,"UTF-8",new Profile[] {profile});
+ }
+
+ public static String encode(char[] chars, Profile... profiles) {
+ return encode(chars,0,chars.length,"UTF-8",profiles);
+ }
+
+ public static String encode(char[] chars, String enc) {
+ return encode(chars,0,chars.length,enc,new Profile[0]);
+ }
+
+ public static String encode(char[] chars, String enc, Profile profile) {
+ return encode(chars,0,chars.length,enc,new Profile[] {profile});
+ }
+
+ public static String encode(char[] chars, String enc, Profile... profiles) {
+ return encode(chars,0,chars.length,enc,profiles);
+ }
+
+ public static String encode(char[] chars, int offset, int length) {
+ return encode(chars,offset,length,"UTF-8",new Profile[0]);
+ }
+
+ public static String encode(char[] chars, int offset, int length, String enc) {
+ return encode(chars,offset,length,enc,new Profile[0]);
+ }
+
+ public static String encode(char[] chars, int offset, int length, Profile profile) {
+ return encode(chars,offset,length,"UTF-8",new Profile[] {profile});
+ }
+
+ public static String encode(char[] chars, int offset, int length, Profile... profiles) {
+ return encode(chars,offset,length,"UTF-8",profiles);
+ }
+
+ public static String encode(char[] chars, int offset, int length, String enc, Profile profile) {
+ return encode(chars,offset,length,enc,new Profile[] {profile});
+ }
+
+ public static String encode(char[] chars, int offset, int length, String enc, Profile... profiles) {
+ try {
+ return encode((CharSequence)CharBuffer.wrap(chars,offset,length),enc,profiles);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String encode(InputStream in) throws IOException {
+ StringBuilder buf = new StringBuilder();
+ byte[] chunk = new byte[1024];
+ int r = -1;
+ while((r = in.read(chunk)) > -1)
+ encode(buf,0,r,chunk);
+ return buf.toString();
+ }
+
+ public static String encode(
+ InputStream in,
+ String charset) throws IOException {
+ return encode(in,charset,"UTF-8",new Profile[0]);
+ }
+
+ public static String encode(
+ InputStream in,
+ String charset,
+ Profile profile)
+ throws IOException {
+ return encode(in,charset,"UTF-8",new Profile[] {profile});
+ }
+
+ public static String encode(
+ InputStream in,
+ String charset,
+ String enc) throws IOException {
+ return encode(in,charset,enc,new Profile[0]);
+ }
+
+ public static String encode(
+ InputStream in,
+ String charset,
+ String enc,
+ Profile profile)
+ throws IOException {
+ return encode(in,charset,enc,new Profile[] {profile});
+ }
+
+ public static String encode(
+ InputStream in,
+ String charset,
+ String enc,
+ Profile... profiles)
+ throws IOException {
+ return encode(new InputStreamReader(in,charset),enc,profiles);
+ }
+
+ public static String encode(
+ InputStream in,
+ String charset,
+ Profile... profiles)
+ throws IOException {
+ return encode(new InputStreamReader(in,charset),"UTF-8",profiles);
+ }
+
+ public static String encode(
+ Reader reader)
+ throws IOException {
+ return encode(reader,"UTF-8", new Profile[0]);
+ }
+
+ public static String encode(
+ Readable readable)
+ throws IOException {
+ return encode(readable,"UTF-8", new Profile[0]);
+ }
+
+ public static String encode(
+ Reader reader,
+ String enc)
+ throws IOException {
+ return encode(reader, enc, new Profile[0]);
+ }
+
+ public static String encode(
+ Readable readable,
+ String enc)
+ throws IOException {
+ return encode(readable, enc, new Profile[0]);
+ }
+
+ public static String encode(
+ Reader reader,
+ String enc,
+ Profile profile)
+ throws IOException {
+ return encode(reader,enc,new Profile[] {profile});
+ }
+
+ public static String encode(
+ Reader reader,
+ Profile profile)
+ throws IOException {
+ return encode(reader,"UTF-8",new Profile[] {profile});
+ }
+
+ public static String encode(
+ Reader reader,
+ Profile... profiles)
+ throws IOException {
+ return encode(reader,"UTF-8",profiles);
+ }
+
+ public static String encode(
+ Readable readable,
+ String enc,
+ Profile profile)
+ throws IOException {
+ return encode(readable,enc,new Profile[] {profile});
+ }
+
+ public static String encode(
+ Readable readable,
+ Profile profile)
+ throws IOException {
+ return encode(readable,"UTF-8",new Profile[] {profile});
+ }
+
+ public static String encode(
+ Readable readable,
+ Profile... profiles)
+ throws IOException {
+ return encode(readable,"UTF-8",profiles);
+ }
+
+ private static void processChars(
+ StringBuilder sb,
+ CharBuffer chars,
+ String enc,
+ Profile... profiles)
+ throws IOException {
+ for (int n = 0; n < chars.length(); n++) {
+ char c = chars.charAt(n);
+ if (!CharUtils.isHighSurrogate(c) && check(c,profiles)) {
+ encode(sb,String.valueOf(c).getBytes(enc));
+ } else if (CharUtils.isHighSurrogate(c)) {
+ if (check(c,profiles)) {
+ StringBuilder buf = new StringBuilder();
+ buf.append(c);
+ buf.append(chars.charAt(++n));
+ byte[] b = buf.toString().getBytes(enc);
+ encode(sb,b);
+ } else {
+ sb.append(c);
+ sb.append(chars.charAt(++n));
+ }
+ } else {
+ sb.append(c);
+ }
+ }
+ }
+
+ public static String encode(
+ Readable readable,
+ String enc,
+ Profile... profiles)
+ throws IOException {
+ StringBuilder sb = new StringBuilder();
+ CharBuffer chars = CharBuffer.allocate(1024);
+ while (readable.read(chars) > -1) {
+ chars.flip();
+ processChars(sb, chars, enc, profiles);
+ }
+ return sb.toString();
+ }
+
+ public static String encode(
+ Reader reader,
+ String enc,
+ Profile... profiles)
+ throws IOException {
+ StringBuilder sb = new StringBuilder();
+ char[] chunk = new char[1024];
+ int r = -1;
+ while ((r = reader.read(chunk)) > -1)
+ processChars(
+ sb, CharBuffer.wrap(chunk, 0, r),
+ enc, profiles);
+ return sb.toString();
+ }
+
+ public static String encode(byte... bytes) {
+ StringBuilder buf = new StringBuilder();
+ encode(buf,bytes);
+ return buf.toString();
+ }
+
+ public static String encode(byte[] bytes, int off, int len) {
+ StringBuilder buf = new StringBuilder();
+ encode(buf,off,len,bytes);
+ return buf.toString();
+ }
+
+ public static String encode(CharSequence s) {
return encode(s,Profile.NONE);
}
- public static String encode(String s, Profile profile) {
+ public static String encode(CharSequence s, Profile profile) {
return encode(s, new Profile[] {profile});
}
- public static String encode(String s, Profile... profiles) {
+ public static String encode(CharSequence s, Profile... profiles) {
try {
if (s == null) return null;
return encode(s,"utf-8",profiles);
@@ -67,35 +328,64 @@
}
}
+ public static String encode(CharSequence s, int offset, int length) {
+ return encode(s,offset,length,Profile.NONE);
+ }
+
+ public static String encode(CharSequence s, int offset, int length, Profile profile) {
+ return encode(s,offset,length, new Profile[] {profile});
+ }
+
+ public static String encode(CharSequence s, int offset, int length, Profile... profiles) {
+ try {
+ if (s == null) return null;
+ return encode(s,offset,length,"utf-8",profiles);
+ } catch (UnsupportedEncodingException e) {
+ return null; // shouldn't happen
+ }
+ }
+
private static boolean check(int codepoint, Profile... profiles) {
for (Profile profile : profiles) {
if (!profile.check(codepoint)) return false;
}
return true;
}
+
+ public static String encode(
+ CharSequence s,
+ int offset,
+ int length,
+ String enc,
+ Profile... profiles)
+ throws UnsupportedEncodingException {
+ int end = Math.min(s.length(), offset+length);
+ CharSequence seq = s.subSequence(offset, end);
+ return encode(seq,enc,profiles);
+ }
public static String encode(
- String s,
+ CharSequence s,
String enc,
Profile... profiles)
throws UnsupportedEncodingException {
- if (s == null) return s;
+ if (s == null) return s.toString();
StringBuilder sb = new StringBuilder();
- char[] chars = s.toCharArray();
- for (int n = 0; n < chars.length; n++) {
- char c = (char) chars[n];
+
+ for (int n = 0; n < s.length(); n++) {
+ char c = s.charAt(n);
if (!CharUtils.isHighSurrogate(c) && check(c,profiles)) {
encode(sb,String.valueOf(c).getBytes(enc));
} else if (CharUtils.isHighSurrogate(c)) {
if (check(c,profiles)) {
StringBuilder buf = new StringBuilder();
buf.append(c);
- buf.append(chars[++n]);
+ buf.append(s.charAt(++n));
byte[] b = buf.toString().getBytes(enc);
encode(sb,b);
} else {
sb.append(c);
- sb.append(chars[++n]);
+ sb.append(s.charAt(++n));
}
} else {
sb.append(c);
@@ -123,13 +413,86 @@
}
}
- public static class DecodingInputStream
- extends ByteArrayInputStream {
+ public static class EncodingOutputStream
+ extends FilterOutputStream {
+
+ public EncodingOutputStream(OutputStream out) {
+ super(out);
+ }
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ String enc = encode(b,off,len);
+ out.write(enc.getBytes("UTF-8"));
+ }
+ @Override
+ public void write(byte[] b) throws IOException {
+ String enc = encode(b);
+ out.write(enc.getBytes("UTF-8"));
+ }
+ @Override
+ public void write(int b) throws IOException {
+ String enc = encode((byte)b);
+ out.write(enc.getBytes("UTF-8"));
+ }
+ }
+
+ public static class EncodingWriter
+ extends FilterWriter {
+ private final Profile[] profiles;
+ public EncodingWriter(OutputStream out) {
+ this(new OutputStreamWriter(out));
+ }
+ public EncodingWriter(OutputStream out,Profile profile) {
+ this(new OutputStreamWriter(out),profile);
+ }
+ public EncodingWriter(OutputStream out,Profile... profiles) {
+ this(new OutputStreamWriter(out),profiles);
+ }
+ public EncodingWriter(Writer out) {
+ this(out,new Profile[0]);
+ }
+ public EncodingWriter(Writer out, Profile profile) {
+ this(out,new Profile[] {profile});
+ }
+ public EncodingWriter(Writer out, Profile... profiles) {
+ super(out);
+ this.profiles = profiles;
+ }
+ @Override
+ public void write(char[] b, int off, int len) throws IOException {
+ String enc = encode(b,off,len,profiles);
+ out.write(enc.toCharArray());
+ }
+ @Override
+ public void write(char[] b) throws IOException {
+ String enc = encode(b,profiles);
+ out.write(enc.toCharArray());
+ }
+ @Override
+ public void write(int b) throws IOException {
+ String enc = encode(new char[] {(char)b},profiles);
+ out.write(enc.toCharArray());
+ }
+ @Override
+ public void write(
+ String str,
+ int off,
+ int len)
+ throws IOException {
+ String enc = encode(str,off,len,profiles);
+ out.write(enc.toCharArray());
+ }
+ }
- DecodingInputStream(byte[] buf) {
- super(buf);
+ public static class DecodingInputStream
+ extends FilterInputStream {
+ public DecodingInputStream(InputStream in) {
+ super(in);
+ }
+ public DecodingInputStream(byte[] in) {
+ super(new ByteArrayInputStream(in));
}
- public int read() {
+ public int read() throws IOException {
int c = super.read();
if (c == '%') {
int c1 = super.read();
@@ -140,7 +503,7 @@
}
}
@Override
- public synchronized int read(byte[] b, int off, int len) {
+ public synchronized int read(byte[] b, int off, int len) throws IOException {
int n = off;
int i = -1;
while ((i = read()) != -1 && n < off+len) {
@@ -148,19 +511,73 @@
}
return n - off;
}
+ @Override
+ public int read(byte[] b) throws IOException {
+ return read(b,0,b.length);
+ }
+ @Override
+ public long skip(long n) throws IOException {
+ long i = 0;
+ for (; i < n; i++) read();
+ return i;
+ }
+
}
public static class DecodingReader
- extends InputStreamReader {
- public DecodingReader(byte[] buf) {
- super(new DecodingInputStream(buf));
- }
- public DecodingReader(
- byte[] buf,
- String encoding)
- throws UnsupportedEncodingException {
- super(new DecodingInputStream(buf),encoding);
+ extends FilterReader {
+ public DecodingReader(byte[] buf)
+ throws UnsupportedEncodingException {
+ this(new ByteArrayInputStream(buf));
+ }
+ public DecodingReader(
+ byte[] buf,String enc)
+ throws UnsupportedEncodingException {
+ this(new ByteArrayInputStream(buf),enc);
+ }
+ public DecodingReader(
+ InputStream in)
+ throws UnsupportedEncodingException {
+ this(in, "UTF-8");
+ }
+ public DecodingReader(
+ InputStream in,
+ String enc)
+ throws UnsupportedEncodingException {
+ this(new InputStreamReader(in,enc));
+ }
+ public DecodingReader(Reader in) {
+ super(in);
+ }
+ public int read() throws IOException {
+ int c = super.read();
+ if (c == '%') {
+ int c1 = super.read();
+ int c2 = super.read();
+ return decode((char)c1,(char)c2);
+ } else {
+ return c;
}
+ }
+ @Override
+ public synchronized int read(char[] b, int off, int len) throws IOException {
+ int n = off;
+ int i = -1;
+ while ((i = read()) != -1 && n < off+len) {
+ b[n++] = (char)i;
+ }
+ return n - off;
+ }
+ @Override
+ public int read(char[] b) throws IOException {
+ return read(b,0,b.length);
+ }
+ @Override
+ public long skip(long n) throws IOException {
+ long i = 0;
+ for (; i < n; i++) read();
+ return i;
+ }
}
private static byte decode(char c, int shift) {
Modified: incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/HashMapContext.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/HashMapContext.java?rev=600056&r1=600055&r2=600056&view=diff
==============================================================================
--- incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/HashMapContext.java (original)
+++ incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/HashMapContext.java Sat Dec 1 00:11:39 2007
@@ -39,6 +39,11 @@
public HashMapContext(Map<String,Object> map) {
super(map);
}
+
+ public HashMapContext(Map<String,Object> map, boolean isiri) {
+ super(map);
+ this.isiri = isiri;
+ }
public <T> T resolve(String var) {
return (T)get(var);
Modified: incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Operation.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Operation.java?rev=600056&r1=600055&r2=600056&view=diff
==============================================================================
--- incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Operation.java (original)
+++ incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Operation.java Sat Dec 1 00:11:39 2007
@@ -18,6 +18,7 @@
package org.apache.abdera.i18n.templates;
import java.io.IOException;
+import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
@@ -103,25 +104,25 @@
Object value = context.resolve(token);
if (value != null) {
if (value instanceof String) {
- String val = (String) value;
+ String val = toString(value,context);
if (val != null && val.length() > 0)
- buf.append(encode(val,context.isIri(),context.isNormalizing()));
+ buf.append(val);
} else if (value.getClass().isArray()) {
Object[] values = (Object[])value;
for (Object obj : values) {
- String val = toString(obj);
+ String val = toString(obj,context);
if (val != null && val.length() > 0) {
if (buf.length() > 0) buf.append(sep);
- buf.append(encode(val,context.isIri(),context.isNormalizing()));
+ buf.append(val);
}
}
} else if (value instanceof Iterable) {
Iterable iterable = (Iterable)value;
for (Object obj : iterable) {
- String val = toString(obj);
+ String val = toString(obj,context);
if (val != null && val.length() > 0) {
if (buf.length() > 0) buf.append(sep);
- buf.append(encode(val,context.isIri(),context.isNormalizing()));
+ buf.append(val);
}
}
}
@@ -134,15 +135,113 @@
String var = vardef[0];
String def = vardef.length > 1 ? vardef[1] : null;
Object rep = context.resolve(var);
- String val = toString(rep);
+ String val = toString(rep,context);
return val != null && val.length() > 0 ?
- encode(rep.toString(),context.isIri(),context.isNormalizing()) :
- def != null ?
- def : null;
+ val : def != null ? def : null;
}
- private static String toString(Object val) {
- return val != null ? val.toString() : null;
+ private static String toString(Object val, Context context) {
+ if (val == null) return null;
+ if (val.getClass().isArray()) {
+ if (val instanceof byte[]) {
+ return Escaping.encode((byte[])val);
+ } else if (val instanceof char[]) {
+ try {
+ String chars = new String((char[])val);
+ return Escaping.encode(
+ !context.isNormalizing() ? chars :
+ Normalizer.normalize(
+ chars,
+ Normalizer.Form.C).toString(),
+ context.isIri() ?
+ CharUtils.Profile.IUNRESERVED :
+ CharUtils.Profile.UNRESERVED);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ } else if (val instanceof short[]) {
+ StringBuilder buf = new StringBuilder();
+ short[] array = (short[]) val;
+ for (short obj : array)
+ buf.append(String.valueOf(obj));
+ return buf.toString();
+ } else if (val instanceof int[]) {
+ StringBuilder buf = new StringBuilder();
+ int[] array = (int[]) val;
+ for (int obj : array)
+ buf.append(String.valueOf(obj));
+ return buf.toString();
+ } else if (val instanceof long[]) {
+ StringBuilder buf = new StringBuilder();
+ long[] array = (long[]) val;
+ for (long obj : array)
+ buf.append(String.valueOf(obj));
+ return buf.toString();
+ } else if (val instanceof double[]) {
+ StringBuilder buf = new StringBuilder();
+ double[] array = (double[]) val;
+ for (double obj : array)
+ buf.append(String.valueOf(obj));
+ return buf.toString();
+ } else if (val instanceof float[]) {
+ StringBuilder buf = new StringBuilder();
+ float[] array = (float[]) val;
+ for (float obj : array)
+ buf.append(String.valueOf(obj));
+ return buf.toString();
+ } else if (val instanceof boolean[]) {
+ StringBuilder buf = new StringBuilder();
+ boolean[] array = (boolean[]) val;
+ for (boolean obj : array)
+ buf.append(String.valueOf(obj));
+ return buf.toString();
+ } else {
+ StringBuilder buf = new StringBuilder();
+ Object[] array = (Object[]) val;
+ for (Object obj : array)
+ buf.append(toString(obj,context));
+ return buf.toString();
+ }
+ } else if (val instanceof Template) {
+ return toString(((Template)val).getPattern(),context);
+ } else if (val instanceof InputStream) {
+ try {
+ return Escaping.encode((InputStream)val);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ } else if (val instanceof Readable) {
+ try {
+ return Escaping.encode(
+ (Readable)val,
+ "UTF-8",
+ context.isIri() ?
+ CharUtils.Profile.IUNRESERVED :
+ CharUtils.Profile.UNRESERVED);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ } else if (val instanceof CharSequence) {
+ return encode(
+ (CharSequence)val,
+ context.isIri(),
+ context.isNormalizing());
+ } else if (val instanceof Byte) {
+ return Escaping.encode(((Byte)val).byteValue());
+ } else if (val instanceof Iterable) {
+ StringBuilder buf = new StringBuilder();
+ Iterable i = (Iterable) val;
+ for (Object obj : i)
+ buf.append(toString(obj,context));
+ return buf.toString();
+ } else {
+ return encode(
+ val != null ?
+ val.toString() :
+ null,
+ context.isIri(),
+ context.isNormalizing());
+ }
}
protected static String eval(String token, String arg, Context context) {
@@ -155,31 +254,31 @@
if (rep.getClass().isArray()) {
Object[] array = (Object[]) rep;
for (Object obj : array) {
- String val = toString(obj);
+ String val = toString(obj,context);
if (val != null && val.length() > 0) {
if (buf.length() > 0) buf.append(arg);
buf.append(var);
buf.append("=");
- buf.append(encode(val,context.isIri(),context.isNormalizing()));
+ buf.append(val);
}
}
} else if (rep instanceof Iterable) {
Iterable list = (Iterable)rep;
for (Object obj : list) {
- String val = toString(obj);
+ String val = toString(obj,context);
if (val != null && val.length() > 0) {
if (buf.length() > 0) buf.append(arg);
buf.append(var);
buf.append("=");
- buf.append(encode(val,context.isIri(),context.isNormalizing()));
+ buf.append(val);
}
}
} else {
- String val = toString(rep);
+ String val = toString(rep,context);
if (val != null && val.length() > 0) {
buf.append(var);
buf.append("=");
- buf.append(encode(val,context.isIri(),context.isNormalizing()));
+ buf.append(val);
}
}
return buf.toString();
@@ -202,11 +301,11 @@
if (rep.getClass().isArray()) {
Object[] a = (Object[])rep;
return a.length > 0;
- } else return true;
+ } else return toString(rep,context).length() > 0;
}
private static String encode(
- String val,
+ CharSequence val,
boolean isiri,
boolean normalizing) {
try {
@@ -217,8 +316,7 @@
Normalizer.Form.C).toString(),
isiri ?
CharUtils.Profile.IUNRESERVED :
- CharUtils.Profile.UNRESERVED,
- CharUtils.Profile.PCT);
+ CharUtils.Profile.UNRESERVED);
} catch (IOException e) {
throw new RuntimeException(e);
}
Modified: incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Template.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Template.java?rev=600056&r1=600055&r2=600056&view=diff
==============================================================================
--- incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Template.java (original)
+++ incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/templates/Template.java Sat Dec 1 00:11:39 2007
@@ -26,6 +26,8 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.abdera.i18n.io.CharUtils;
+
/**
* Used to evaluate a URI Template.
* Instances are immutable, cloneable, serializable and threadsafe.
@@ -52,7 +54,7 @@
*/
public Template(
String pattern) {
- this.pattern = pattern;
+ this.pattern = CharUtils.stripBidiInternal(pattern);
this.tokens = initTokens();
this.variables = initVariables();
}
@@ -65,6 +67,35 @@
}
/**
+ * IRI Templates that contain bidirectional characters will
+ * typically not display properly in unicode enabled environments.
+ * This method return the Template with appropriate bidi control
+ * characters to ensure that the Template can be rendered properly
+ * for display
+ */
+ public String getPatternForDisplay() {
+ String pattern = this.pattern;
+ for(String token : this) {
+ pattern = replace(
+ pattern,
+ token,
+ "{" + forDisplay(token) + "}");
+ }
+ return CharUtils.bidiLRM(pattern);
+ }
+
+ private static String forDisplay(String token) {
+ //return token.replaceAll("([^{}|]*)", "\u200E$1\u200E");
+ String[] splits = token.split("\\|");
+ String d = "";
+ for (String s : splits) {
+ if (d.length() > 0) d+= "|";
+ d += CharUtils.bidiLRM(s);
+ }
+ return d;
+ }
+
+ /**
* Iterate the template tokens
*/
public Iterator<String> iterator() {
@@ -141,7 +172,7 @@
object instanceof Context ?
(Context)object :
object instanceof Map ?
- new HashMapContext((Map)object) :
+ new HashMapContext((Map)object,isiri) :
new ObjectContext(object,isiri));
}
Modified: incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/unicode/Normalizer.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/unicode/Normalizer.java?rev=600056&r1=600055&r2=600056&view=diff
==============================================================================
--- incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/unicode/Normalizer.java (original)
+++ incubator/abdera/java/trunk/dependencies/i18n/src/main/java/org/apache/abdera/i18n/unicode/Normalizer.java Sat Dec 1 00:11:39 2007
@@ -65,7 +65,7 @@
/**
* Normalize the string using NFKC
*/
- public static String normalize(String source) throws IOException {
+ public static String normalize(CharSequence source) throws IOException {
return normalize(source, Form.KC);
}
@@ -73,7 +73,7 @@
* Normalize the string using the specified Form
*/
public static String normalize(
- String source,
+ CharSequence source,
Form form)
throws IOException {
return normalize(source, form, new StringBuilder());
@@ -83,7 +83,7 @@
* Normalize the string into the given StringBuilder using the given Form
*/
public static String normalize(
- String source,
+ CharSequence source,
Form form,
StringBuilder buf)
throws IOException {
@@ -95,7 +95,7 @@
}
private static void decompose(
- String source,
+ CharSequence source,
Form form,
StringBuilder buf)
throws IOException {
Modified: incubator/abdera/java/trunk/dependencies/i18n/src/test/java/org/apache/abdera/i18n/test/iri/TestTemplate.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/dependencies/i18n/src/test/java/org/apache/abdera/i18n/test/iri/TestTemplate.java?rev=600056&r1=600055&r2=600056&view=diff
==============================================================================
--- incubator/abdera/java/trunk/dependencies/i18n/src/test/java/org/apache/abdera/i18n/test/iri/TestTemplate.java (original)
+++ incubator/abdera/java/trunk/dependencies/i18n/src/test/java/org/apache/abdera/i18n/test/iri/TestTemplate.java Sat Dec 1 00:11:39 2007
@@ -17,6 +17,7 @@
*/
package org.apache.abdera.i18n.test.iri;
+import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -220,6 +221,10 @@
map.put("reserved",":/?#[]@!$&'()*+,;=");
map.put("u","\u2654\u2655");
map.put("a_b","baz");
+ map.put("bytes", new byte[] {'a','b','c'});
+ map.put("stream", new ByteArrayInputStream(new byte[] {'a','b','c'}));
+ map.put("chars", new char[] {'a','b','c','/'});
+ map.put("ints", new int[] {1,2,3});
Map<String,String> tests = new HashMap<String,String>();
tests.put("http://example.org/?q={a}","http://example.org/?q=foo");
@@ -237,6 +242,10 @@
tests.put("http://example.org/?d={-listjoin|&d=|points}","http://example.org/?d=10&d=20&d=30");
tests.put("http://example.org/{a}{b}/{a_b}","http://example.org/foobar/baz");
tests.put("http://example.org/{a}{-prefix|/-/|a}/","http://example.org/foo/-/foo/");
+ tests.put("{bytes}","%61%62%63");
+ tests.put("{stream}","%61%62%63");
+ tests.put("{chars}","abc%2F");
+ tests.put("{ints}","123");
for (String t : tests.keySet())
assertEquals(Template.expand(t,map),tests.get(t));