You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/09 17:15:26 UTC

[05/44] incubator-juneau git commit: Rename CT_* testcases.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
new file mode 100755
index 0000000..2b76236
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
@@ -0,0 +1,114 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+public class ClassUtilsTest {
+
+	//====================================================================================================
+	// getReadableClassName(Class)
+	// getReadableClassName(String)
+	//====================================================================================================
+	@Test
+	public void testGetReadableClassName() throws Exception {
+		assertEquals("java.lang.Object", getReadableClassName(Object.class));
+		assertEquals("java.lang.Object[]", getReadableClassName(Object[].class));
+		assertEquals("java.lang.Object[][]", getReadableClassName(Object[][].class));
+
+		assertEquals("boolean", getReadableClassName(boolean.class));
+		assertEquals("boolean[]", getReadableClassName(boolean[].class));
+		assertEquals("boolean[][]", getReadableClassName(boolean[][].class));
+
+		assertEquals("byte", getReadableClassName(byte.class));
+		assertEquals("byte[]", getReadableClassName(byte[].class));
+		assertEquals("byte[][]", getReadableClassName(byte[][].class));
+
+		assertEquals("char", getReadableClassName(char.class));
+		assertEquals("char[]", getReadableClassName(char[].class));
+		assertEquals("char[][]", getReadableClassName(char[][].class));
+
+		assertEquals("double", getReadableClassName(double.class));
+		assertEquals("double[]", getReadableClassName(double[].class));
+		assertEquals("double[][]", getReadableClassName(double[][].class));
+
+		assertEquals("float", getReadableClassName(float.class));
+		assertEquals("float[]", getReadableClassName(float[].class));
+		assertEquals("float[][]", getReadableClassName(float[][].class));
+
+		assertEquals("int", getReadableClassName(int.class));
+		assertEquals("int[]", getReadableClassName(int[].class));
+		assertEquals("int[][]", getReadableClassName(int[][].class));
+
+		assertEquals("long", getReadableClassName(long.class));
+		assertEquals("long[]", getReadableClassName(long[].class));
+		assertEquals("long[][]", getReadableClassName(long[][].class));
+
+		assertEquals("short", getReadableClassName(short.class));
+		assertEquals("short[]", getReadableClassName(short[].class));
+		assertEquals("short[][]", getReadableClassName(short[][].class));
+
+		assertNull(getReadableClassName((Class<?>)null));
+		assertNull(getReadableClassName((String)null));
+	}
+
+	//====================================================================================================
+	// isParentClass(Class, Class)
+	//====================================================================================================
+	@Test
+	public void testIsParentClass() throws Exception {
+
+		// Strict
+		assertTrue(isParentClass(A.class, A1.class, true));
+		assertTrue(isParentClass(A1.class, A2.class, true));
+		assertTrue(isParentClass(Object.class, A2.class, true));
+		assertFalse(isParentClass(A.class, A.class, true));
+		assertFalse(isParentClass(A1.class, A1.class, true));
+		assertFalse(isParentClass(A2.class, A2.class, true));
+		assertFalse(isParentClass(A2.class, A1.class, true));
+		assertFalse(isParentClass(A1.class, A.class, true));
+		assertFalse(isParentClass(A2.class, Object.class, true));
+
+		// Not strict
+		assertTrue(isParentClass(A.class, A1.class, false));
+		assertTrue(isParentClass(A1.class, A2.class, false));
+		assertTrue(isParentClass(Object.class, A2.class, false));
+		assertTrue(isParentClass(A.class, A.class, false));
+		assertTrue(isParentClass(A1.class, A1.class, false));
+		assertTrue(isParentClass(A2.class, A2.class, false));
+		assertFalse(isParentClass(A2.class, A1.class, false));
+		assertFalse(isParentClass(A1.class, A.class, false));
+		assertFalse(isParentClass(A2.class, Object.class, false));
+	}
+
+	public interface A {}
+
+	public static class A1 implements A {}
+
+	public static class A2 extends A1 {}
+
+	//====================================================================================================
+	// getReadableClassNames(Object[])
+	//====================================================================================================
+	@Test
+	public void testGetReadableClassNames() throws Exception {
+		assertEquals("['java.lang.String','java.lang.Integer','java.lang.Boolean','null']", getReadableClassNames(new Object[]{"a",1,true,null}).toString());
+	}
+
+	public void getClassFromReadableName() throws Exception {
+		fail("Not implemented");
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
new file mode 100755
index 0000000..b0446d7
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
@@ -0,0 +1,34 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.apache.juneau.internal.CollectionUtils.*;
+import static org.junit.Assert.*;
+
+import org.apache.juneau.*;
+import org.junit.*;
+
+public class CollectionUtilsTest {
+
+	//====================================================================================================
+	// reverse(LinkedHashMap)
+	//====================================================================================================
+	@Test
+	public void testReverse() throws Exception {
+		assertNull(reverse(null));
+
+		assertObjectEquals("{b:2,a:1}", reverse(new ObjectMap("{a:1,b:2}")));
+		assertObjectEquals("{}", reverse(new ObjectMap("{}")));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/FilteredMapTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
new file mode 100755
index 0000000..b09ac9d
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
@@ -0,0 +1,44 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+public class FilteredMapTest {
+
+	Map<?,?> m3;
+
+	//====================================================================================================
+	// testBasic
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+		ObjectMap m = new ObjectMap("{a:'1',b:'2'}");
+		FilteredMap<String,Object> m2 = new FilteredMap<String,Object>(m, new String[]{"a"});
+
+		assertObjectEquals("{a:'1'}", m2);
+
+		m2.entrySet().iterator().next().setValue("3");
+		assertObjectEquals("{a:'3'}", m2);
+
+		try { m3 = new FilteredMap<String,String>(null, new String[0]); fail(); } catch (IllegalArgumentException e) {}
+		try { m3 = new FilteredMap<String,Object>(m, null); fail(); } catch (IllegalArgumentException e) {}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/IOPipeTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/IOPipeTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/IOPipeTest.java
new file mode 100755
index 0000000..6d9a1be
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/IOPipeTest.java
@@ -0,0 +1,282 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+
+import org.apache.juneau.internal.*;
+import org.apache.juneau.utils.IOPipe.*;
+import org.junit.*;
+
+public class IOPipeTest {
+
+	//====================================================================================================
+	// IOPipe(Object input, Object output)
+	//====================================================================================================
+	@Test
+	public void testConstructor() throws Exception {
+		try { IOPipe.create(null, new StringWriter()); fail(); } catch (IllegalArgumentException e) {}
+		try { IOPipe.create(new StringReader(""), null); fail(); } catch (IllegalArgumentException e) {}
+		try { IOPipe.create(new Integer(1), new StringWriter()); fail(); } catch (IllegalArgumentException e) {}
+		try { IOPipe.create("", new Integer(1)); fail(); } catch (IllegalArgumentException e) {}
+	}
+
+	//====================================================================================================
+	// closeOut()
+	// close(boolean in, boolean out)
+	//====================================================================================================
+	@Test
+	public void testClose() throws Exception {
+		TestReader in;
+		TestWriter out;
+		TestInputStream in2;
+		TestOutputStream out2;
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).run();
+		assertTrue(in.closed);
+		assertFalse(out.closed);
+		assertEquals("foobar", out.toString());
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).closeOut().run();
+		assertTrue(in.closed);
+		assertTrue(out.closed);
+		assertEquals("foobar", out.toString());
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).close(false, true).run();
+		assertFalse(in.closed);
+		assertTrue(out.closed);
+		assertEquals("foobar", out.toString());
+
+		in2 = new TestInputStream("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in2, out2).run();
+		assertTrue(in2.closed);
+		assertFalse(out2.closed);
+		assertEquals("foobar", out2.toString());
+
+		in2 = new TestInputStream("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in2, out2).closeOut().run();
+		assertTrue(in2.closed);
+		assertTrue(out2.closed);
+		assertEquals("foobar", out2.toString());
+
+		in2 = new TestInputStream("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in2, out2).close(false, true).run();
+		assertFalse(in2.closed);
+		assertTrue(out2.closed);
+		assertEquals("foobar", out2.toString());
+
+		in = new TestReader("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in, out2).run();
+		assertTrue(in.closed);
+		assertFalse(out2.closed);
+		assertEquals("foobar", out.toString());
+
+		in = new TestReader("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in, out2).closeOut().run();
+		assertTrue(in.closed);
+		assertTrue(out2.closed);
+		assertEquals("foobar", out.toString());
+
+		in = new TestReader("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in, out2).close(false, true).run();
+		assertFalse(in.closed);
+		assertTrue(out2.closed);
+		assertEquals("foobar", out.toString());
+
+		in2 = new TestInputStream("foobar");
+		out = new TestWriter();
+		IOPipe.create(in2, out).run();
+		assertTrue(in2.closed);
+		assertFalse(out.closed);
+		assertEquals("foobar", out2.toString());
+
+		in2 = new TestInputStream("foobar");
+		out = new TestWriter();
+		IOPipe.create(in2, out).closeOut().run();
+		assertTrue(in2.closed);
+		assertTrue(out.closed);
+		assertEquals("foobar", out2.toString());
+
+		in2 = new TestInputStream("foobar");
+		out = new TestWriter();
+		IOPipe.create(in2, out).close(false, true).run();
+		assertFalse(in2.closed);
+		assertTrue(out.closed);
+		assertEquals("foobar", out2.toString());
+	}
+
+
+	public static class TestReader extends StringReader {
+		boolean closed;
+
+		public TestReader(String s) {
+			super(s);
+		}
+
+		@Override /* Reader */
+		public void close() {
+			closed = true;
+		}
+	}
+
+	public static class TestWriter extends StringWriter {
+		boolean closed;
+
+		public TestWriter() {
+			super();
+		}
+
+		@Override /* Writer */
+		public void close() {
+			closed = true;
+		}
+	}
+
+	public static class TestInputStream extends ByteArrayInputStream {
+		boolean closed;
+
+		public TestInputStream(String s) {
+			super(s.getBytes());
+		}
+
+		@Override /* InputStream */
+		public void close() throws IOException {
+			super.close();
+			closed = true;
+		}
+	}
+
+	public static class TestOutputStream extends ByteArrayOutputStream {
+		boolean closed;
+
+		public TestOutputStream() {
+			super();
+		}
+
+		@Override /* OutputStream */
+		public void close() throws IOException {
+			super.close();
+			closed = true;
+		}
+
+		@Override /* Object */
+		public String toString() {
+			return new String(this.toByteArray(), IOUtils.UTF8);
+		}
+	}
+
+	//====================================================================================================
+	// byLines()
+	// byLines(boolean)
+	//====================================================================================================
+	@Test
+	public void testByLines() throws Exception {
+		TestReader in;
+		TestWriter out;
+
+		in = new TestReader("foo\nbar");
+		out = new TestWriter() {
+			@Override public void write(String s) {
+				super.write("["+s+"]");
+			}
+		};
+		IOPipe.create(in, out).byLines().run();
+		assertEquals("[foo][][bar][]", out.toString().replaceAll("[\\r\\n]", ""));
+
+		in = new TestReader("foo\nbar");
+		out = new TestWriter() {
+			@Override public void write(String s) {
+				super.write("["+s+"]");
+			}
+		};
+		IOPipe.create(in, out).byLines(true).run();
+		assertEquals("[foo][][bar][]", out.toString().replaceAll("[\\r\\n]", ""));
+
+		in = new TestReader("foo\nbar");
+		out = new TestWriter() {
+			@Override public void write(String s) {
+				super.write("["+s+"]");
+			}
+		};
+		IOPipe.create(in, out).byLines(false).run();
+		assertEquals("foo\nbar", out.toString());
+	}
+
+	//====================================================================================================
+	// lineProcessor()
+	//====================================================================================================
+	@Test
+	public void testLineProcessor() throws Exception {
+		TestReader in;
+		TestWriter out;
+		LineProcessor lp = new LineProcessor() {
+			@Override /* LineProcessor */
+			public String process(String line) {
+				return "[" + line + "]";
+			}
+		};
+
+		in = new TestReader("foo\nbar");
+		out = new TestWriter();
+		IOPipe.create(in, out).lineProcessor(lp).run();
+		assertEquals("[foo][bar]", out.toString().replaceAll("[\\r\\n]", ""));
+
+		LineProcessor lp2 = new LineProcessor() {
+			@Override /* LineProcessor */
+			public String process(String line) {
+				return line.equals("foo") ? null : line;
+			}
+		};
+		in = new TestReader("foo\nbar");
+		out = new TestWriter();
+		IOPipe.create(in, out).lineProcessor(lp2).run();
+		assertEquals("bar", out.toString().replaceAll("[\\r\\n]", ""));
+
+		TestInputStream in2;
+		TestOutputStream out2;
+		in2 = new TestInputStream("foo\nbar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in2, out2).lineProcessor(lp).run();
+		assertEquals("[foo][bar]", out2.toString().replaceAll("[\\r\\n]", ""));
+	}
+
+	//====================================================================================================
+	// buffSize()
+	//====================================================================================================
+	@Test
+	public void testBuffSize() throws Exception {
+		TestReader in;
+		TestWriter out;
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).buffSize(1).run();
+		assertEquals("foobar", out.toString().replaceAll("[\\r\\n]", ""));
+
+		try { IOPipe.create(in, out).buffSize(0); fail(); } catch (IllegalArgumentException e) {}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/IOUtilsTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/IOUtilsTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/IOUtilsTest.java
new file mode 100755
index 0000000..596d5bb
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/IOUtilsTest.java
@@ -0,0 +1,103 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+public class IOUtilsTest {
+
+	//====================================================================================================
+	// read(File)
+	// read(InputStream, Charset)
+	// read(InputStream)
+	// read(Reader, int, int)
+	//====================================================================================================
+	@Test
+	public void testRead() throws Exception {
+
+		TestReader in;
+		TestWriter out;
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).run();
+		assertTrue(in.closed);
+		assertFalse(out.closed);
+		assertEquals("foobar", out.toString());
+	}
+
+
+	public static class TestReader extends StringReader {
+		boolean closed;
+
+		public TestReader(String s) {
+			super(s);
+		}
+
+		@Override /* Reader */
+		public void close() {
+			closed = true;
+		}
+	}
+
+	public static class TestWriter extends StringWriter {
+		boolean closed;
+
+		public TestWriter() {
+			super();
+		}
+
+		@Override /* Writer */
+		public void close() {
+			closed = true;
+		}
+	}
+
+	public static class TestInputStream extends ByteArrayInputStream {
+		boolean closed;
+
+		public TestInputStream(String s) {
+			super(s.getBytes());
+		}
+
+		@Override /* InputStream */
+		public void close() throws IOException {
+			super.close();
+			closed = true;
+		}
+	}
+
+	public static class TestOutputStream extends ByteArrayOutputStream {
+		boolean closed;
+
+		public TestOutputStream() {
+			super();
+		}
+
+		@Override /* OutputStream */
+		public void close() throws IOException {
+			super.close();
+			closed = true;
+		}
+
+		@Override /* Object */
+		public String toString() {
+			return new String(this.toByteArray(), IOUtils.UTF8);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/IdentityListTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/IdentityListTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/IdentityListTest.java
new file mode 100755
index 0000000..e554e49
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/IdentityListTest.java
@@ -0,0 +1,38 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+public class IdentityListTest {
+
+	//====================================================================================================
+	// test - Basic tests
+	//====================================================================================================
+	@Test
+	public void test() throws Exception {
+		List<String> l = new IdentityList<String>();
+		String a = "a";
+		l.add(a);
+		l.add(a);
+		l.add("b");
+		assertEquals(2, l.size());
+		assertTrue(l.contains("a"));
+		assertFalse(l.contains("c"));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/KeywordStoreTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/KeywordStoreTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/KeywordStoreTest.java
new file mode 100755
index 0000000..b267b06
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/KeywordStoreTest.java
@@ -0,0 +1,45 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+public class KeywordStoreTest {
+
+	//====================================================================================================
+	// test - Basic tests
+	//====================================================================================================
+	@Test
+	public void test() throws Exception {
+		KeywordSet ks = new KeywordSet("aaa", "zzz");
+		assertTrue(ks.contains("aaa"));
+		assertTrue(ks.contains("zzz"));
+		assertFalse(ks.contains("xxx"));
+		assertFalse(ks.contains("aaaa"));
+		assertFalse(ks.contains("zzzz"));
+		assertFalse(ks.contains("\u0000\u1000"));
+		assertFalse(ks.contains("z"));
+		assertFalse(ks.contains(null));
+		assertFalse(ks.contains("a|"));
+		assertFalse(ks.contains("|a"));
+		assertFalse(ks.contains("Aa"));
+		assertFalse(ks.contains("aA"));
+
+		for (String s : new String[]{"a","aA","Aa","a|","|a"}) {
+			try { ks = new KeywordSet(s); fail(); } catch (IllegalArgumentException e) {}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/MultiIterableTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/MultiIterableTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/MultiIterableTest.java
new file mode 100755
index 0000000..2418b44
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/MultiIterableTest.java
@@ -0,0 +1,70 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+public class MultiIterableTest {
+
+	//====================================================================================================
+	// Basic tests
+	//====================================================================================================
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	@Test
+	public void test() throws Exception {
+		List
+			l1 = new ObjectList(),
+			l2 = new ObjectList("['a','b']"),
+			l3 = new ObjectList("['c']");
+
+		MultiIterable mi = new MultiIterable(l1.iterator(),l2.iterator());
+		mi.append(l3.iterator());
+
+		assertObjectEquals("['a','b','c']", mi.iterator());
+
+		mi = new MultiIterable(l1.iterator());
+		assertObjectEquals("[]", mi.iterator());
+
+		mi = new MultiIterable(l2.iterator(), l1.iterator());
+		assertObjectEquals("['a','b']", mi.iterator());
+
+		mi = new MultiIterable(l2.iterator(), l1.iterator(), l3.iterator());
+		assertObjectEquals("['a','b','c']", mi.iterator());
+
+		mi = new MultiIterable();
+		assertObjectEquals("[]", mi.iterator());
+
+		try { mi.append(null); fail(); } catch (IllegalArgumentException e) {}
+
+		mi = new MultiIterable(l1.iterator());
+		try { mi.iterator().next(); fail(); } catch (NoSuchElementException e) {}
+
+		mi = new MultiIterable(l1.iterator());
+		Iterator i = mi.iterator();
+		assertFalse(i.hasNext());
+		try { i.remove(); fail(); } catch (NoSuchElementException e) {}
+
+		mi = new MultiIterable(l2.iterator());
+		i = mi.iterator();
+		assertTrue(i.hasNext());
+		assertEquals("a", i.next());
+		i.remove();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/MultiSetTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/MultiSetTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/MultiSetTest.java
new file mode 100755
index 0000000..4d6d927
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/MultiSetTest.java
@@ -0,0 +1,143 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+public class MultiSetTest {
+
+	@Test
+	@SuppressWarnings({ "unchecked" })
+	public void doTest() throws Exception {
+		List<String> l1, l2;
+		MultiSet<String> ms;
+		Iterator<String> i;
+
+		l1 = Arrays.asList(new String[]{"1","2"});
+		l2 = Arrays.asList(new String[]{"3","4"});
+		ms = new MultiSet<String>(l1, l2);
+		i = ms.iterator();
+		assertTrue(i.hasNext());
+		assertEquals("1", i.next());
+		assertTrue(i.hasNext());
+		assertEquals("2", i.next());
+		assertTrue(i.hasNext());
+		assertEquals("3", i.next());
+		assertTrue(i.hasNext());
+		assertEquals("4", i.next());
+		assertFalse(i.hasNext());
+		try {
+			i.next();
+			fail("Exception expected");
+		} catch (NoSuchElementException e) {
+		}
+
+		l1 = Arrays.asList(new String[]{"1","2"});
+		l2 = Arrays.asList(new String[]{});
+		ms = new MultiSet<String>(l1, l2);
+		i = ms.iterator();
+		assertTrue(i.hasNext());
+		assertEquals("1", i.next());
+		assertTrue(i.hasNext());
+		assertEquals("2", i.next());
+		assertFalse(i.hasNext());
+		try {
+			i.next();
+			fail("Exception expected");
+		} catch (NoSuchElementException e) {
+		}
+
+		l1 = Arrays.asList(new String[]{});
+		l2 = Arrays.asList(new String[]{"3","4"});
+		ms = new MultiSet<String>(l1, l2);
+		i = ms.iterator();
+		assertTrue(i.hasNext());
+		assertEquals("3", i.next());
+		assertTrue(i.hasNext());
+		assertEquals("4", i.next());
+		assertFalse(i.hasNext());
+		try {
+			i.next();
+			fail("Exception expected");
+		} catch (NoSuchElementException e) {
+		}
+
+		l1 = Arrays.asList(new String[]{});
+		l2 = Arrays.asList(new String[]{});
+		ms = new MultiSet<String>(l1, l2);
+		i = ms.iterator();
+		assertFalse(i.hasNext());
+		try {
+			i.next();
+			fail("Exception expected");
+		} catch (NoSuchElementException e) {
+		}
+
+		l1 = Arrays.asList(new String[]{"1","2"});
+		ms = new MultiSet<String>(l1);
+		i = ms.iterator();
+		assertTrue(i.hasNext());
+		assertEquals("1", i.next());
+		assertTrue(i.hasNext());
+		assertEquals("2", i.next());
+		assertFalse(i.hasNext());
+		try {
+			i.next();
+			fail("Exception expected");
+		} catch (NoSuchElementException e) {
+		}
+
+		l1 = new LinkedList<String>(Arrays.asList(new String[]{"1","2"}));
+		l2 = new LinkedList<String>(Arrays.asList(new String[]{"3","4"}));
+		ms = new MultiSet<String>(l1).append(l2);
+		assertObjectEquals("['1','2','3','4']", ms);
+		assertObjectEquals("['1','2','3','4']", ms.enumerator());
+		assertEquals(4, ms.size());
+
+		Iterator<String> t = ms.iterator();
+		t.next();
+		t.remove();
+		assertObjectEquals("['2','3','4']", ms.enumerator());
+
+		t = ms.iterator();
+		t.next();
+		t.remove();
+		assertObjectEquals("['3','4']", ms.enumerator());
+
+		t = ms.iterator();
+		t.next();
+		t.remove();
+		assertObjectEquals("['4']", ms.enumerator());
+
+		t = ms.iterator();
+		t.next();
+		t.remove();
+		assertObjectEquals("[]", ms.enumerator());
+		assertEquals(0, ms.size());
+
+		ms = new MultiSet<String>();
+		assertObjectEquals("[]", ms);
+		assertEquals(0, ms.size());
+
+		try { ms = new MultiSet<String>((Collection<String>)null); fail(); } catch (IllegalArgumentException e) {}
+		try { new MultiSet<String>().iterator().next(); fail(); } catch (NoSuchElementException e) {}
+		try { new MultiSet<String>().iterator().remove(); fail(); } catch (NoSuchElementException e) {}
+
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/ParserReaderTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/ParserReaderTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/ParserReaderTest.java
new file mode 100755
index 0000000..c4b7e01
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/ParserReaderTest.java
@@ -0,0 +1,48 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.parser.*;
+import org.junit.*;
+
+public class ParserReaderTest {
+
+	//====================================================================================================
+	// test
+	//====================================================================================================
+	@Test
+	public void test() throws Exception {
+		ParserReader r = new ParserReader("abc123");
+		try {
+			assertEquals('a', r.read());
+			r.unread();
+			assertEquals('a', r.read());
+			assertEquals('b', r.read());
+			r.unread();
+			assertEquals("bc", r.read(2));
+			assertEquals('1', r.read());
+			r.unread();
+			r.read();
+			assertEquals('2', r.peek());
+			assertEquals('2', r.peek());
+			assertEquals('2', r.read());
+			assertEquals('3', r.read());
+			assertEquals(-1, r.read());
+			assertEquals(-1, r.read());
+		} finally {
+			r.close();
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/PojoIntrospectorTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/PojoIntrospectorTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/PojoIntrospectorTest.java
new file mode 100755
index 0000000..e6f3868
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/PojoIntrospectorTest.java
@@ -0,0 +1,53 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+public class PojoIntrospectorTest {
+
+	//====================================================================================================
+	// testBasic
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+		String in = null;
+		Object r;
+
+		r = new PojoIntrospector(in, null).invokeMethod("substring(int,int)", "[3,6]");
+		assertNull(r);
+
+		in = "foobar";
+		r = new PojoIntrospector(in).invokeMethod("substring(int,int)", "[3,6]");
+		assertEquals("bar", r);
+
+		r = new PojoIntrospector(in).invokeMethod("toString", null);
+		assertEquals("foobar", r);
+
+		r = new PojoIntrospector(in).invokeMethod("toString", "");
+		assertEquals("foobar", r);
+
+		r = new PojoIntrospector(in).invokeMethod("toString", "[]");
+		assertEquals("foobar", r);
+
+		try { new PojoIntrospector(in).invokeMethod("noSuchMethod", "[3,6]"); fail(); } catch (NoSuchMethodException e) {}
+
+		r = new PojoIntrospector(null).invokeMethod(String.class.getMethod("toString"), null);
+		assertNull(r);
+
+		r = new PojoIntrospector("foobar").invokeMethod(String.class.getMethod("toString"), null);
+		assertEquals("foobar", r);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/utils/PojoQueryTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/utils/PojoQueryTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/utils/PojoQueryTest.java
new file mode 100755
index 0000000..3c405a3
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/utils/PojoQueryTest.java
@@ -0,0 +1,680 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.juneau.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transforms.*;
+import org.junit.*;
+
+@SuppressWarnings({"serial","rawtypes"})
+public class PojoQueryTest {
+
+	//====================================================================================================
+	// filterCollection, string search, 1 level
+	//====================================================================================================
+	@Test
+	public void testFilterCollectionStringSearchOneLevel() throws Exception {
+		ObjectMap query = null;
+		List view = null;
+		List sort = null;
+		int pos = 0;
+		int limit = 0;
+		boolean ignoreCase = false;
+		BeanContext bc = BeanContext.DEFAULT;
+		List results;
+
+		List<A> in = new LinkedList<A>() {{
+			add(new A("foo"));
+			add(new A("bar"));
+			add(new A("baz"));
+		}};
+
+		PojoQuery filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'foo'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:'foo'}]", results);
+
+		query = new ObjectMap("{f:'fo*'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:'foo'}]", results);
+
+		query = new ObjectMap("{f:'*ar'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:'bar'}]", results);
+
+		query = new ObjectMap("{f:'foo bar'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:'foo'},{f:'bar'}]", results);
+	}
+
+	public class A {
+		public String f;
+
+		A() {}
+
+		A(String f) {
+			this.f = f;
+		}
+	}
+
+	//====================================================================================================
+	// filterCollection, date search, 1 level
+	//====================================================================================================
+	@Test
+	public void testFilterCollectionDateSearchOneLevel() throws Exception {
+		ObjectMap query = null;
+		List view = null;
+		List sort = null;
+		int pos = 0;
+		int limit = 0;
+		boolean ignoreCase = false;
+		BeanContext bc = BeanContext.DEFAULT;
+		WriterSerializer s = new JsonSerializer.Simple().addTransforms(CalendarTransform.Simple.class);
+		B[] in;
+		PojoQuery filter;
+
+		List results;
+
+		in = new B[] {
+			new B(2010, 0, 1),
+			new B(2011, 0, 1),
+			new B(2011, 0, 31),
+			new B(2012, 0, 1)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'2011'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 00:00:00'},{f:'2011/01/31 00:00:00'}]", s.serialize(results));
+
+		query = new ObjectMap("{f:'2011.01'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 00:00:00'},{f:'2011/01/31 00:00:00'}]", s.serialize(results));
+
+		query = new ObjectMap("{f:'2011.01.01'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 00:00:00'}]", s.serialize(results));
+
+		in = new B[] {
+			new B(2011, 00, 01, 11, 59, 59),
+			new B(2011, 00, 01, 12, 00, 00),
+			new B(2011, 00, 01, 12, 59, 59),
+			new B(2011, 00, 01, 13, 00, 00)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'2011.01.01.12'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 12:00:00'},{f:'2011/01/01 12:59:59'}]", s.serialize(results));
+
+		in = new B[] {
+			new B(2011, 00, 01, 12, 29, 59),
+			new B(2011, 00, 01, 12, 30, 00),
+			new B(2011, 00, 01, 12, 30, 59),
+			new B(2011, 00, 01, 12, 31, 00)
+		};
+		filter = new PojoQuery(in, bc);
+		query = new ObjectMap("{f:'2011.01.01.12.30'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 12:30:00'},{f:'2011/01/01 12:30:59'}]", s.serialize(results));
+
+		in = new B[] {
+			new B(2011, 00, 01, 12, 30, 29),
+			new B(2011, 00, 01, 12, 30, 30),
+			new B(2011, 00, 01, 12, 30, 31)
+		};
+		filter = new PojoQuery(in, bc);
+		query = new ObjectMap("{f:'2011.01.01.12.30.30'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 12:30:30'}]", s.serialize(results));
+
+		// Open-ended ranges
+
+		in = new B[] {
+			new B(2000, 11, 31),
+			new B(2001, 00, 01)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'>2000'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2001/01/01 00:00:00'}]", s.serialize(results));
+
+		query = new ObjectMap("{f:'>=2001'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2001/01/01 00:00:00'}]", s.serialize(results));
+
+		query = new ObjectMap("{f:'<2001'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2000/12/31 00:00:00'}]", s.serialize(results));
+
+		query = new ObjectMap("{f:'<=2000'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2000/12/31 00:00:00'}]", s.serialize(results));
+
+		in = new B[] {
+			new B(2011, 00, 01, 12, 29, 59),
+			new B(2011, 00, 01, 12, 30, 00)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'>=2011.01.01.12.30'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 12:30:00'}]", s.serialize(results));
+
+		query = new ObjectMap("{f:'<2011.01.01.12.30'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 12:29:59'}]", s.serialize(results));
+
+		in = new B[] {
+			new B(2011, 00, 01, 12, 30, 59),
+			new B(2011, 00, 01, 12, 31, 00)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'>2011.01.01.12.30'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 12:31:00'}]", s.serialize(results));
+
+		query = new ObjectMap("{f:'<=2011.01.01.12.30'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2011/01/01 12:30:59'}]", s.serialize(results));
+
+		// Closed range
+
+		in = new B[] {
+			new B(2000, 11, 31, 23, 59, 59),
+			new B(2001, 00, 01, 00, 00, 00),
+			new B(2003, 05, 30, 23, 59, 59),
+			new B(2003, 06, 01, 00, 00, 00)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'2001 - 2003.06.30'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2001/01/01 00:00:00'},{f:'2003/06/30 23:59:59'}]", s.serialize(results));
+
+		// ORed timestamps
+
+		in = new B[] {
+			new B(2000, 11, 31),
+			new B(2001, 00, 01),
+			new B(2001, 11, 31),
+			new B(2002, 00, 01)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'2001 2003 2005'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2001/01/01 00:00:00'},{f:'2001/12/31 00:00:00'}]", s.serialize(results));
+
+		in = new B[] {
+			new B(2002, 11, 31),
+			new B(2003, 00, 01),
+			new B(2003, 11, 31),
+			new B(2004, 00, 01)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'2001 2003 2005'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2003/01/01 00:00:00'},{f:'2003/12/31 00:00:00'}]", s.serialize(results));
+
+		in = new B[] {
+			new B(2004, 11, 31),
+			new B(2005, 00, 01),
+			new B(2005, 11, 31),
+			new B(2006, 00, 01)
+		};
+		filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'2001 2003 2005'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f:'2005/01/01 00:00:00'},{f:'2005/12/31 00:00:00'}]", s.serialize(results));
+	}
+
+	public class B {
+		public Calendar f;
+
+		B() {}
+
+		B(int year, int month, int day) {
+			this.f = new GregorianCalendar(year, month, day);
+		}
+
+		B(int year, int month, int day, int hour, int minute, int second) {
+			this.f = new GregorianCalendar(year, month, day, hour, minute, second);
+		}
+	}
+
+	//====================================================================================================
+	// filterCollection, int search, 1 level
+	//====================================================================================================
+	@Test
+	public void testFilterCollectionIntSearchOneLevel() throws Exception {
+		ObjectMap query = null;
+		List view = null;
+		List sort = null;
+		int pos = 0;
+		int limit = 0;
+		boolean ignoreCase = false;
+		BeanContext bc = BeanContext.DEFAULT;
+		List results;
+
+		List<C> in = new LinkedList<C>() {{
+			add(new C(1));
+			add(new C(2));
+			add(new C(3));
+		}};
+
+		PojoQuery filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:'1'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:1}]", results);
+
+		query = new ObjectMap("{f:'>1'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:2},{f:3}]", results);
+
+		query = new ObjectMap("{f:'>=2'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:2},{f:3}]", results);
+
+		query = new ObjectMap("{f:'<=2'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:1},{f:2}]", results);
+
+		query = new ObjectMap("{f:'<2'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:1}]", results);
+
+		query = new ObjectMap("{f:'1 3'}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:1},{f:3}]", results);
+	}
+
+	public class C {
+		public int f;
+
+		C() {}
+
+		C(int f) {
+			this.f = f;
+		}
+	}
+
+	//====================================================================================================
+	// filterCollection, string search, 2 level
+	//====================================================================================================
+	@Test
+	public void testFilterCollectionStringSearchTwoLevel() throws Exception {
+		ObjectMap query = null;
+		List view = null;
+		List sort = null;
+		int pos = 0;
+		int limit = 0;
+		boolean ignoreCase = false;
+		BeanContext bc = BeanContext.DEFAULT;
+		List results;
+
+		List<D1> in = new LinkedList<D1>() {{
+			add(new D1("foo"));
+			add(new D1("bar"));
+			add(new D1("baz"));
+		}};
+
+		PojoQuery filter = new PojoQuery(in, bc);
+
+		query = new ObjectMap("{f:{f:'foo'}}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:{f:'foo'}}]", results);
+
+		query = new ObjectMap("{f:{f:'fo*'}}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:{f:'foo'}}]", results);
+
+		query = new ObjectMap("{f:{f:'*ar'}}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:{f:'bar'}}]", results);
+
+		query = new ObjectMap("{f:{f:'foo bar'}}");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f:{f:'foo'}},{f:{f:'bar'}}]", results);
+	}
+
+	public class D1 {
+		public D2 f;
+
+		D1() {}
+
+		D1(String f) {
+			this.f = new D2(f);
+		}
+	}
+	public class D2 {
+		public String f;
+
+		D2() {}
+
+		D2(String f) {
+			this.f = f;
+		}
+	}
+
+	//====================================================================================================
+	// filterCollection, view, 1 level
+	//====================================================================================================
+	@Test
+	public void testFilterCollectionViewOneLevel() throws Exception {
+		ObjectMap query = null;
+		List view = null;
+		List sort = null;
+		int pos = 0;
+		int limit = 0;
+		boolean ignoreCase = false;
+		BeanContext bc = BeanContext.DEFAULT;
+		List results;
+
+		List<E> in = new LinkedList<E>() {{
+			add(new E("foo", 1, true));
+			add(new E("bar", 2, false));
+			add(new E("baz", 3, true));
+		}};
+
+		PojoQuery filter = new PojoQuery(in, bc);
+
+		view = new ObjectList("['f1']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f1:'foo'},{f1:'bar'},{f1:'baz'}]", results);
+
+		view = new ObjectList("['f2']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f2:1},{f2:2},{f2:3}]", results);
+
+		view = new ObjectList("['f3']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f3:true},{f3:false},{f3:true}]", results);
+
+		view = new ObjectList("['f3','f2','f1']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f3:true,f2:1,f1:'foo'},{f3:false,f2:2,f1:'bar'},{f3:true,f2:3,f1:'baz'}]", results);
+	}
+
+	public class E {
+		public String f1;
+		public int f2;
+		public boolean f3;
+
+		E() {}
+
+		E(String f1, int f2, boolean f3) {
+			this.f1 = f1;
+			this.f2 = f2;
+			this.f3 = f3;
+		}
+	}
+
+	//====================================================================================================
+	// filterCollection, view, 2 level
+	//====================================================================================================
+	@Test
+	public void testFilterCollectionViewTwoLevel() throws Exception {
+		ObjectMap query = null;
+		List view = null;
+		List sort = null;
+		int pos = 0;
+		int limit = 0;
+		boolean ignoreCase = false;
+		BeanContext bc = BeanContext.DEFAULT;
+		List results;
+
+		List<F1> in = new LinkedList<F1>() {{
+			add(new F1("foo"));
+			add(new F1("bar"));
+			add(new F1("baz"));
+		}};
+
+		PojoQuery filter = new PojoQuery(in, bc);
+
+		view = new ObjectList("['f1']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f1:'foo'},{f1:'bar'},{f1:'baz'}]", results);
+
+		view = new ObjectList("[{f2:['f1']}]");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f2:{f1:'f2_foo'}},{f2:{f1:'f2_bar'}},{f2:{f1:'f2_baz'}}]", results);
+
+		view = new ObjectList("['f1',{f3:['f1']}]");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertObjectEquals("[{f1:'foo',f3:[{f1:'f31_foo'},{f1:'f32_foo'}]},{f1:'bar',f3:[{f1:'f31_bar'},{f1:'f32_bar'}]},{f1:'baz',f3:[{f1:'f31_baz'},{f1:'f32_baz'}]}]", results);
+	}
+
+	public class F1 {
+		public String f1;
+		public F2 f2;
+		public List<F2> f3;
+
+		F1() {}
+
+		F1(final String f1) {
+			this.f1 = f1;
+			this.f2 = new F2("f2_"+f1);
+			this.f3 = new LinkedList<F2>() {{
+				add(new F2("f31_"+f1));
+				add(new F2("f32_"+f1));
+			}};
+		}
+	}
+
+	public class F2 {
+		public String f1;
+		public String f2;
+
+		F2() {}
+
+		F2(String f1) {
+			this.f1 = f1;
+			this.f2 = f1;
+		}
+	}
+
+	//====================================================================================================
+	// filterMap, 1 level
+	//===================================================================================================
+	@Test
+	public void testFilterMapOneLevel() throws Exception {
+		ObjectList view = null;
+		BeanContext bc = BeanContext.DEFAULT;
+		Map results;
+
+		G in = new G("foo", 1, true);
+		PojoQuery filter = new PojoQuery(in, bc);
+
+		view = new ObjectList("['f1']");
+		results = filter.filterMap(view);
+		assertObjectEquals("{f1:'foo'}", results);
+
+		view = new ObjectList("['f2']");
+		results = filter.filterMap(view);
+		assertObjectEquals("{f2:1}", results);
+
+		view = new ObjectList("['f3','f1']");
+		results = filter.filterMap(view);
+		assertObjectEquals("{f3:true,f1:'foo'}", results);
+	}
+
+	public class G {
+		public String f1;
+		public int f2;
+		public boolean f3;
+
+		G() {}
+
+		G(String f1, int f2, boolean f3) {
+			this.f1 = f1;
+			this.f2 = f2;
+			this.f3 = f3;
+		}
+	}
+
+	//====================================================================================================
+	// filterMap, 2 level
+	//====================================================================================================
+	@Test
+	public void testFilterMapTwoLevel() throws Exception {
+		ObjectList view = null;
+		BeanContext bc = BeanContext.DEFAULT;
+		Map results;
+
+		H1 in = new H1("foo");
+
+		PojoQuery filter = new PojoQuery(in, bc);
+
+		view = new ObjectList("['f1']");
+		results = filter.filterMap(view);
+		assertObjectEquals("{f1:'foo'}", results);
+
+		view = new ObjectList("[{f2:['f1']}]");
+		results = filter.filterMap(view);
+		assertObjectEquals("{f2:{f1:'f2_foo'}}", results);
+
+		view = new ObjectList("['f1',{f3:['f1']}]");
+		results = filter.filterMap(view);
+		assertObjectEquals("{f1:'foo',f3:[{f1:'f31_foo'},{f1:'f32_foo'}]}", results);
+	}
+
+	public class H1 {
+		public String f1;
+		public H2 f2;
+		public List<H2> f3;
+
+		H1() {}
+
+		H1(final String f1) {
+			this.f1 = f1;
+			this.f2 = new H2("f2_"+f1);
+			this.f3 = new LinkedList<H2>() {{
+				add(new H2("f31_"+f1));
+				add(new H2("f32_"+f1));
+			}};
+		}
+	}
+
+	public class H2 {
+		public String f1;
+		public String f2;
+
+		H2() {}
+
+		H2(String f1) {
+			this.f1 = f1;
+			this.f2 = f1;
+		}
+	}
+
+	//====================================================================================================
+	// testSorting
+	//====================================================================================================
+	@Test
+	public void testSorting() throws Exception {
+		ObjectMap query = null;
+		List view = null;
+		List sort = null;
+		int pos = 0;
+		int limit = 0;
+		boolean ignoreCase = false;
+		BeanContext bc = BeanContext.DEFAULT;
+		WriterSerializer s = new JsonSerializer.Simple().addTransforms(CalendarTransform.Simple.class);
+		List results;
+
+		I[] in = new I[] {
+			new I(1, "foo", true, 2010, 1, 1),
+			new I(2, "bar", false, 2011, 1, 1),
+			new I(3, "baz", true, 2012, 1, 1),
+		};
+
+		PojoQuery filter = new PojoQuery(in, bc);
+
+		sort = new ObjectList("['f2']");
+		view = new ObjectList("['f1','f2']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:2,f2:'bar'},{f1:3,f2:'baz'},{f1:1,f2:'foo'}]", s.serialize(results));
+
+		sort = new ObjectList("[{f2:'d'}]");
+		view = new ObjectList("['f1','f2']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:1,f2:'foo'},{f1:3,f2:'baz'},{f1:2,f2:'bar'}]", s.serialize(results));
+
+		sort = new ObjectList("['f3']");
+		view = new ObjectList("['f1','f3']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:2,f3:false},{f1:1,f3:true},{f1:3,f3:true}]", s.serialize(results));
+
+		sort = new ObjectList("['f3',{f1:'a'}]");
+		view = new ObjectList("['f1','f3']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:2,f3:false},{f1:1,f3:true},{f1:3,f3:true}]", s.serialize(results));
+
+		sort = new ObjectList("['f3',{f1:'d'}]");
+		view = new ObjectList("['f1','f3']");
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:2,f3:false},{f1:3,f3:true},{f1:1,f3:true}]", s.serialize(results));
+
+		sort = new ObjectList("['f1']");
+		view = new ObjectList("['f1']");
+		limit = 1;
+		pos = 0;
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:1}]", s.serialize(results));
+
+		limit = 3;
+		pos = 0;
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:1},{f1:2},{f1:3}]", s.serialize(results));
+
+		limit = 1;
+		pos = 2;
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:3}]", s.serialize(results));
+
+		limit = 100;
+		pos = 2;
+		results = filter.filterCollection(query, view, sort, pos, limit, ignoreCase);
+		assertEquals("[{f1:3}]", s.serialize(results));
+	}
+
+	public class I {
+		public int f1;
+		public String f2;
+		public boolean f3;
+		public Calendar f4;
+
+		I() {}
+
+		I(int f1, String f2, boolean f3, int year, int month, int day) {
+			this.f1 = f1;
+			this.f2 = f2;
+			this.f3 = f3;
+			this.f4 = new GregorianCalendar(year, month, day);
+		}
+	}
+}
\ No newline at end of file