рд▓реЗрдЦ рдЬрд╛рд╡рд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЬрдЯрд┐рд▓ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдЯреИрдВрдб-рдЕрд▓реЛрди рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ "рд╕реЗрд╡рд╛ рдирд░рдХ" рд╕реЗ рдмрдЪрдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИред
рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╡рд┐рд╡рд░рдг
рдПрдХ рдЧрд╣рд░реА рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрд░рдЪрдирд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ
class A{
B b;
}
class B{
C c;
}
class C{
String name;
}
рдЕрдЧрд░ рд╣рдореЗрдВ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдП рддрдХ рд╕реАрдзреА рдкрд╣реБрдВрдЪ рдХреЗ рдмрд┐рдирд╛ рдХреНрд▓рд╛рд╕ рд╕реА рдХреЗ рдирд╛рдо рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд╕реЗрд╡рд╛ рдПрдкреАрдЖрдИ рдХреА рдПрдХ рдордзреНрдпрд╡рд░реНрддреА рдкрд░рдд рдЖрдорддреМрд░ рдкрд░ рдмрдЪрд╛рд╡ рдХреЗ рд▓рд┐рдП рдЖрддреА рд╣реИред
private A a;
public void setNameService(String name) {
a.b.c.name = name;
}
, , . , .
private A a;
public void setNameService(String name) {
if(a == null) {
a = new A();
}
if(a.b == null) {
a.b = new B();
}
if(a.b.c == null) {
a.b.c = new C();
}
a.b.c.name = name;
}
, , setNameService(String name) , , a, b c, , .
API, , , API. . , . , , 'C' name, 'B' 'A' .
, - . , , , . - - . , . , , , , .
JavaPath , .
JavaPath
JavaPath.
private A a = new A();
private final JavaPath javaPath = new JavaPath(A.class);
public void setNameService(String name) {
javaPath.evalPath("b.c.name", a, name);
}
setNameService.
, JavaPath тАФ , Java. JavaPath . , . JavaPath . -public. . JavaPath private final .
: тАФ JavaPath!
final String str = "VALUE";
JavaPath javaPath = new JavaPath(String.class);
assertEquals("VALUE",str);
// private final byte[] value; String
javaPath.evalPath("value",str,"THE HACK".getBytes());
assertEquals("THE HACK",str);
- , , JavaPath Java Reflection .
, JavaPath . . .
JavaPath
public Object evalPath(String path, Object root, Object... values);
evalPath
- тАФ Java
- A тАФ b
- , . тАФ тАФ name
, . C. .
class C{
String name;
public void setName(String name) {
this.name = name;
}
}
. .
A a = new A();
JavaPath javaPath = new JavaPath(A.class);
public void setNameService(String name) {
javaPath.evalPath("b.c.setName", a, name);
}
JavaPath , , , :
javaPath.evalPath("b.c.setName($)", a, name);
$ $0 тАФ .
a0.a1.тАж .an
a0.a1.тАж .an-1
, , / null. an . , , , evalPath. , . JavaPath .
JavaPath
JavaPath , . . . , , , . , , ,
Java . , , , API.

JavaPath . . , , , . . , , , .. тАФ .
$ #

, evalPath $[:digit:]* . $ , . .
.
. : #[:digit:]* # #0
.
, -.
public class A {
A parent;
A child;
String name;
public A(A parent) {
this.parent = parent;
}
}
A a = new A(null);
JavaPath javaPath = new JavaPath(A.class);
javaPath.evalPath("name",a,"PARENT");
javaPath.evalPath("child(#0).name",a,"CHILD");
javaPath.evalPath("child(#0).child(#1).name",a,"GRAND-CHILD");
assertEquals("PARENT",a.name);
assertEquals("CHILD",a.child.name);
assertEquals("GRAND-CHILD",a.child.child.name);
assertEquals("CHILD",a.child.child.parent.name);
assertEquals("PARENT",a.child.child.parent.parent.name);
тАФ .
"a.set('$0')"
InLine :
, JavaPath. , , . .
, , valueOf ( , enum ) .
, valueOf - , StringConverter, .
- null , . .
, , , . тАФ . Java, .
"(T a).b"
: map .
public class A {
Map<String,String> map;
}
A a = new A();
JavaPath javaPath = new JavaPath(A.class);
// map
javaPath.evalPath("(HashMap map).put(firstName,$)", a, "John");
// , .
javaPath.evalPath("map.put(lastName,$)", a, "Silver");
.
javaPath.evalPath("(HashMap map(int 100,float '0.8')).put(firstName,$)", a, "John");
, null. map .
enum PhoneType{HOME,CELL,WORK}
public static class A {
String firstName;
String lastName;
Map<PhoneType, Set<String>> phones;
Map<String, PhoneType> reversedPhones;
}
A a = new A();
ClassRegistry classRegistry = new ClassRegistry();
classRegistry.registerClass(PhoneType.class,PhoneType.class.getSimpleName());
JavaPath javaPath = new JavaPath(A.class,classRegistry);
javaPath.evalPath("(map phones).put(PhoneType WORK)", a, new HashSet<>());
javaPath.evalPath("phones.computeIfAbsent(PhoneType HOME,key->new HashSet).@", a);
javaPath.evalPath("phones.computeIfAbsent(PhoneType CELL,key->new HashSet).@", a);
javaPath.evalPath("(map reversedPhones).@", a);
javaPath.evalPath("firstName", a, "John");
javaPath.evalPath("lastName", a, "Smith");
javaPath.evalPath("phones.get(PhoneType CELL).add", a, "1-101-111-2233");
javaPath.evalPath("phones.get(PhoneType HOME).add", a, "1-101-111-7865");
javaPath.evalPath("phones.get(PhoneType WORK).add", a, "1-105-333-1100");
javaPath.evalPath("phones.get(PhoneType WORK).add($)", a, "1-105-333-1104");
javaPath.evalPath("reversedPhones.put($,PhoneType CELL)", a, "1-101-111-2233");
javaPath.evalPath("reversedPhones.put($,PhoneType HOME)", a, "1-101-111-7865");
javaPath.evalPath("reversedPhones.put($,PhoneType WORK)", a, "1-105-333-1100");
javaPath.evalPath("reversedPhones.put($,PhoneType WORK)", a, "1-105-333-1104");
@
@ . , . .
||
null, JavaPath . .
::
, -, ::
ClassRegistry
, , .. ClassRegistry , JavaPath.
ClassRegistry . ClassRegistry, JavaPath.
PhoneType
ClassRegistry classRegistry = new ClassRegistry();
classRegistry.registerClass(PhoneType.class,PhoneType.class.getSimpleName(),"Phone");
JavaPath javaPath = new JavaPath(A.class,classRegistry);
PhoneType , , Phone.
ClassRegistry . , :: .
. ClassRegistry . , StringConverter тАФ .
public class A {
...
static {
ClassRegistry.registerGlobalStringConverter(A.class,A::stringToA);
}
public static A stringToA(String str) {
A a = new A("{"+str+"}");
return a;
}
}
public class B {
A a;
}
JavaPath javaPath = new JavaPath(B.class); // A::stringToA
@PathElement @NoPathElement
@PathElement .
public class A {
String name;
@PathElement({"name","first_name","firstName"})
public void setName(String name) {
this.name = name;
}
}
, setName "name", . .
@NoPathElement JavaPath.
public class A {
StringBuilder stringBuilder = new StringBuilder();
@NoPathElement
private final String protectedField = "IMMUTABLE BY JAVA PATH!";
public void add(String str) {
stringBuilder.append(str == null ? "N/A" : str);
}
@NoPathElement
public void add(Object val) {
stringBuilder.append(val);
}
}
.
JavaPath . .
public class A {
String firstName;
String lastName;
int age;
}
A a = new A();
JavaPath javaPath = new JavaPath(A.class);
javaPath.evalPath("firstName; lastName; age", a, "John","Smith",55);
javaPath.evalPath("firstName($); lastName($); age($)", a, "John","Smith",55);
javaPath.evalPath("firstName($0); lastName($1); age($2)", a, "John","Smith",55);
'$', , . , firstName($) "John" ( , ), age($) тАФ 55 ( , ). .
, , .
. .
JavaPath
, . , ? initPath
.
JavaPath . , . , , root. # #0
initPath .
:
Object instanceOfA = javaPath.initPath("(com.my.project.A #0).b", "test");
A instanceOfA = javaPath.initPath(A.class, "#.b", "test");
// , # #0
A instanceOfA = javaPath.initPath(A.class, "root.b", "test");
JavaPath рд╡рд░реНрдЧ рдХреА setEnablePathCaching (рдмреВрд▓рд┐рдпрди рдЗрдиреЗрдмрд▓ рдХреЛрдЪрд┐рдВрдЧ) рд╡рд┐рдзрд┐ рдЖрдкрдХреЛ рдкрд╛рд░реНрд╕рд░ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдХреИрд╢ рдореЗрдВ рд╕рд╣реЗрдЬрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рдлрд╝реАрд▓реНрдб рдкрджрд╛рдиреБрдХреНрд░рдо рдФрд░ рд╡рд░реНрдЧ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдЧреИрд░-рдирд┐рд╖реНрдХреНрд░рд┐рдп рдХреИрд╢рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рднреНрд░рдорд┐рдд рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдкрде рдХреИрд╢ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЕрдХреНрд╖рдо рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рдореЗрдореЛрд░реА рдЦрдкрдд рдХрд╛ рдХрд╛рд░рдг рдмрди рд╕рдХрддрд╛ рд╣реИ рдпрджрд┐ рдкрде рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИред
рдЙрджрд╛рд╣рд░рдг - рдХреИрд╢ рдореЗрдВ рддреАрди рдЕрд▓рдЧ-рдЕрд▓рдЧ рд░рд╛рд╕реНрддреЗ рд╣реЛрдВрдЧреЗ:
evalPath("user.name('John'));"
evalPath("user.name('Peter'));"
evalPath("user.name('Mike'));"
рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЧреБрдЬрд░ рдЪрд░ рдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдиреАрдЪреЗ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рдПрдХ рд░рд╛рд╕реНрддрд╛ рдмрдЪрд╛рдПрдЧрд╛ред
evalPath("user.name($0)","John");
evalPath("user.name($0)","Peter");
evalPath("user.name($0)","Mike");
рдирд┐рд░реНрднрд░рддрд╛
Java8 рдФрд░ рдкреБрд░рд╛рдиреЗ
рдорд╛рд╡реЗрди рднрдВрдбрд╛рд░
<dependency>
<groupId>com.aegisql</groupId>
<artifactId>java-path</artifactId>
<version>0.2.0</version>
</dependency>