/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed 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 com.alibaba.citrus.generictype.introspect;
import static com.alibaba.citrus.test.TestUtil.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static org.junit.Assert.*;
import java.util.List;
import com.alibaba.citrus.generictype.introspect.PropertyPath.Visitor;
import org.junit.Test;
/**
* 测试<code>PropertyPath</code>。
*
* @author Michael Zhou
*/
public class PropertyPathTests {
@Test(expected = NullPointerException.class)
public void parse_null() {
PropertyPath.parse(null);
}
@Test
public void parse_propertyNames() {
assertParser("");
assertParser("abc", "abc");
assertParser("a123", "a123");
assertParser(".abc", "abc");
assertParser(" abc ", "abc");
assertParser(" . abc ", "abc");
assertParser("abc.def", "abc", "def");
assertParser(".abc.def", "abc", "def");
assertParser(" abc .def ", "abc", "def");
assertParser(" . abc . def ", "abc", "def");
assertParser("abc.def.ghi", "abc", "def", "ghi");
assertParser(" abc . def. ghi ", "abc", "def", "ghi");
assertParserFail("123", "");
assertParserFail("a.123", "a.");
assertParserFail("a b", "a ");
assertParserFail("a.", "a.");
}
@Test
public void parse_index() {
assertParser("[123]", "[123]");
assertParser("[123][345]", "[123]", "[345]");
assertParser(" [ 123 ] ", "[123]");
assertParser(" [ 123 ] [ 345 ]", "[123]", "[345]");
assertParser("abc[123]", "abc", "[123]");
assertParser("abc [123]", "abc", "[123]");
assertParser(" abc [ 123 ] ", "abc", "[123]");
assertParser("abc[123][456]", "abc", "[123]", "[456]");
assertParser(" abc [ 123 ] [ 456 ] ", "abc", "[123]", "[456]");
assertParserFail("[123a]", "[123");
assertParserFail("[abc]", "[");
assertParserFail("[123", "[123");
assertParserFail("[12 3]", "[12 ");
assertParserFail("abc.[123]", "abc.");
}
@Test
public void parse_key_doubleQuote() {
assertParser("[\"123\"]", "[\"123\"]");
assertParser("[\"123\"][\"345\"]", "[\"123\"]", "[\"345\"]");
assertParser(" [ \"123\" ] ", "[\"123\"]");
assertParser(" [ \"123\" ] [ \"345\" ]", "[\"123\"]", "[\"345\"]");
assertParser("abc[\"123\"]", "abc", "[\"123\"]");
assertParser("abc [\"123\"]", "abc", "[\"123\"]");
assertParser(" abc [ \"123\" ] ", "abc", "[\"123\"]");
assertParser("abc[\"123\"][\"456\"]", "abc", "[\"123\"]", "[\"456\"]");
assertParser(" abc [ \"123\" ] [ \"456\" ] ", "abc", "[\"123\"]", "[\"456\"]");
assertParserFail("[\"123\"", "[\\\"123\\\"");
assertParserFail("[\"123", "[\\\"123");
assertParserFail("[\"12 3]", "[\\\"12 3]");
assertParserFail("abc.[\"123\"]", "abc.");
}
@Test
public void parse_key_singleQuote() {
assertParser("['123']", "[\"123\"]");
assertParser("['123']['345']", "[\"123\"]", "[\"345\"]");
assertParser(" [ '123' ] ", "[\"123\"]");
assertParser(" [ '123' ] [ '345' ]", "[\"123\"]", "[\"345\"]");
assertParser("abc['123']", "abc", "[\"123\"]");
assertParser("abc ['123']", "abc", "[\"123\"]");
assertParser(" abc [ '123' ] ", "abc", "[\"123\"]");
assertParser("abc['123']['456']", "abc", "[\"123\"]", "[\"456\"]");
assertParser(" abc [ '123' ] [ '456' ] ", "abc", "[\"123\"]", "[\"456\"]");
assertParserFail("['123'", "['123'");
assertParserFail("['123", "['123");
assertParserFail("['12 3]", "['12 3]");
assertParserFail("abc.['123']", "abc.");
}
@Test
public void parse_key_escape() {
assertParser("['\\u02-3']", "[\"\\\\u02-3\"]");
assertParser("['\\u02-3\\u4e2d']", "[\"\\\\u02-3中\"]");
assertParser("['test']", "[\"test\"]");
assertParser("['\ntest\b']", "[\"\\ntest\\b\"]");
assertParser("['\u4e2d25foo\ntest\b']", "[\"中25foo\\ntest\\b\"]");
assertParser("['\\'\foo\teste\r']", "[\"'\\foo\\teste\\r\"]");
assertParserFail("['\\']", "['\\\\']");
}
@Test
public void parse_with_visitor() {
String propPath = "abc['abc'][123].def[1234]";
MyVisitor visitor;
// success=false
visitor = new MyVisitor();
visitor.success = false;
PropertyPath.parse(propPath, visitor);
assertArrayEquals(new String[] { "abc[abc]", "abc", "[abc]", "[123]", "def[1234].last", "def", "[1234].last" },
visitor.getResults());
assertArrayEquals(new String[] { "abc['abc']", "abc", "abc['abc']", "abc['abc'][123]",
"abc['abc'][123].def[1234]", "abc['abc'][123].def", "abc['abc'][123].def[1234]" }, visitor
.getDisplayNames());
// success=true
visitor = new MyVisitor();
visitor.success = true;
PropertyPath.parse(propPath, visitor);
assertArrayEquals(new String[] { "abc[abc]", "[123]", "def[1234].last" }, visitor.getResults());
assertArrayEquals(new String[] { "abc['abc']", "abc['abc'][123]", "abc['abc'][123].def[1234]" }, visitor
.getDisplayNames());
// another prop path
propPath = " abc [ 'abc' ] [ 123 ] . def ";
// success=false
visitor = new MyVisitor();
visitor.success = false;
PropertyPath.parse(propPath, visitor);
assertArrayEquals(new String[] { "abc[abc]", "abc", "[abc]", "[123]", "def.last" }, visitor.getResults());
assertArrayEquals(new String[] { " abc [ 'abc' ]", " abc", " abc [ 'abc' ]", " abc [ 'abc' ] [ 123 ]",
" abc [ 'abc' ] [ 123 ] . def" }, visitor.getDisplayNames());
// success=true
visitor = new MyVisitor();
visitor.success = true;
PropertyPath.parse(propPath, visitor);
assertArrayEquals(new String[] { "abc[abc]", "[123]", "def.last" }, visitor.getResults());
assertArrayEquals(new String[] { " abc [ 'abc' ]", " abc [ 'abc' ] [ 123 ]", " abc [ 'abc' ] [ 123 ] . def" },
visitor.getDisplayNames());
}
@Test
public void node_accept_with_visitor() {
String propPath = "abc['abc'][123].def[1234]";
PropertyPath path = PropertyPath.parse(propPath);
MyVisitor visitor;
// success=false
visitor = new MyVisitor();
visitor.success = false;
path.accept(visitor);
assertArrayEquals(new String[] { "abc[abc]", "abc", "[abc]", "[123]", "def[1234].last", "def", "[1234].last" },
visitor.getResults());
assertArrayEquals(new String[] { "abc['abc']", "abc", "abc['abc']", "abc['abc'][123]",
"abc['abc'][123].def[1234]", "abc['abc'][123].def", "abc['abc'][123].def[1234]" }, visitor
.getDisplayNames());
// success=true
visitor = new MyVisitor();
visitor.success = true;
path.accept(visitor);
assertArrayEquals(new String[] { "abc[abc]", "[123]", "def[1234].last" }, visitor.getResults());
assertArrayEquals(new String[] { "abc['abc']", "abc['abc'][123]", "abc['abc'][123].def[1234]" }, visitor
.getDisplayNames());
// another prop path
propPath = " abc [ 'abc' ] [ 123 ] . def ";
path = PropertyPath.parse(propPath);
// success=false
visitor = new MyVisitor();
visitor.success = false;
path.accept(visitor);
assertArrayEquals(new String[] { "abc[abc]", "abc", "[abc]", "[123]", "def.last" }, visitor.getResults());
assertArrayEquals(new String[] { " abc [ 'abc' ]", " abc", " abc [ 'abc' ]", " abc [ 'abc' ] [ 123 ]",
" abc [ 'abc' ] [ 123 ] . def" }, visitor.getDisplayNames());
// success=true
visitor = new MyVisitor();
visitor.success = true;
path.accept(visitor);
assertArrayEquals(new String[] { "abc[abc]", "[123]", "def.last" }, visitor.getResults());
assertArrayEquals(new String[] { " abc [ 'abc' ]", " abc [ 'abc' ] [ 123 ]", " abc [ 'abc' ] [ 123 ] . def" },
visitor.getDisplayNames());
}
private class MyVisitor implements Visitor {
private List<String> results = createLinkedList();
private List<String> displayNames = createLinkedList();
private boolean success;
public String[] getResults() {
return results.toArray(new String[results.size()]);
}
public String[] getDisplayNames() {
return displayNames.toArray(new String[displayNames.size()]);
}
public boolean visitIndexedProperty(String propertyName, int index, String displayName, boolean last) {
results.add(String.format("%s[%d]%s", propertyName, index, last ? ".last" : ""));
displayNames.add(displayName);
return success;
}
public boolean visitMappedProperty(String propertyName, String key, String displayName, boolean last) {
results.add(String.format("%s[%s]%s", propertyName, key, last ? ".last" : ""));
displayNames.add(displayName);
return success;
}
public void visitSimpleProperty(String propertyName, String displayName, boolean last) {
results.add(String.format("%s%s", propertyName, last ? ".last" : ""));
displayNames.add(displayName);
}
public void visitIndex(int index, String displayName, boolean last) {
results.add(String.format("[%d]%s", index, last ? ".last" : ""));
displayNames.add(displayName);
}
public void visitKey(String key, String displayName, boolean last) {
results.add(String.format("[%s]%s", key, last ? ".last" : ""));
displayNames.add(displayName);
}
}
private void assertParser(String pathStr, String... results) {
PropertyPath path = PropertyPath.parse(pathStr);
List<String> nodes = createLinkedList();
for (PropertyPath.Node node : path.getNodes()) {
nodes.add(node.toString());
}
assertArrayEquals(results, nodes.toArray(new String[nodes.size()]));
}
private void assertParserFail(String pathStr, String near) {
try {
PropertyPath.parse(pathStr);
fail();
} catch (InvalidPropertyPathException e) {
assertThat(e, exception("near \"" + near + "\""));
}
}
}