2020
2121package com .arangodb .springframework .repository ;
2222
23+ import java .lang .annotation .Annotation ;
2324import java .util .HashSet ;
2425import java .util .Map ;
2526import java .util .Optional ;
3132import org .springframework .data .mapping .PersistentPropertyAccessor ;
3233import org .springframework .util .Assert ;
3334
35+ import com .arangodb .springframework .core .convert .resolver .ReferenceResolver ;
36+ import com .arangodb .springframework .core .convert .resolver .ResolverFactory ;
3437import com .arangodb .springframework .core .mapping .ArangoMappingContext ;
3538import com .arangodb .springframework .core .mapping .ArangoPersistentEntity ;
3639import com .arangodb .springframework .core .mapping .ArangoPersistentProperty ;
3740
3841/**
39- * Converts Example to String representing predicate expression and puts necessary bindings in the given bindVars Map
42+ * Converts Example to String representing predicate expression and puts
43+ * necessary bindings in the given bindVars Map
4044 */
4145public class ArangoExampleConverter <T > {
4246
4347 private final ArangoMappingContext context ;
48+ private final ResolverFactory resolverFactory ;
4449
45- public ArangoExampleConverter (final ArangoMappingContext context ) {
50+ public ArangoExampleConverter (final ArangoMappingContext context , final ResolverFactory resolverFactory ) {
4651 this .context = context ;
52+ this .resolverFactory = resolverFactory ;
4753 }
4854
4955 public String convertExampleToPredicate (final Example <T > example , final Map <String , Object > bindVars ) {
5056 final StringBuilder predicateBuilder = new StringBuilder ();
5157 final ArangoPersistentEntity <?> persistentEntity = context .getPersistentEntity (example .getProbeType ());
5258 Assert .isTrue (example .getProbe () != null , "Probe in Example cannot be null" );
53- traversePropertyTree (example , predicateBuilder , bindVars , "" , "" , persistentEntity , example .getProbe ());
59+ final String bindEntintyName = "e" ;
60+ traversePropertyTree (example , predicateBuilder , bindVars , "" , "" , persistentEntity , example .getProbe (),
61+ bindEntintyName );
5462 return predicateBuilder .toString ();
5563 }
5664
57- private void traversePropertyTree (
58- final Example <T > example ,
59- final StringBuilder predicateBuilder ,
60- final Map <String , Object > bindVars ,
61- final String path ,
62- final String javaPath ,
63- final ArangoPersistentEntity <?> entity ,
64- final Object object ) {
65+ private void traversePropertyTree (final Example <T > example , final StringBuilder predicateBuilder ,
66+ final Map <String , Object > bindVars , final String path , final String javaPath ,
67+ final ArangoPersistentEntity <?> entity , final Object object , final String bindEntintyName ) {
6568 final PersistentPropertyAccessor <?> accessor = entity .getPropertyAccessor (object );
6669 entity .doWithProperties ((final ArangoPersistentProperty property ) -> {
6770 if (property .getFrom ().isPresent () || property .getTo ().isPresent () || property .getRelations ().isPresent ()) {
@@ -70,13 +73,35 @@ private void traversePropertyTree(
7073 final String fullPath = path + (path .length () == 0 ? "" : "." ) + property .getFieldName ();
7174 final String fullJavaPath = javaPath + (javaPath .length () == 0 ? "" : "." ) + property .getName ();
7275 final Object value = accessor .getProperty (property );
73- if (property .isEntity () && value != null ) {
76+
77+ if (property .isCollectionLike () && value != null ) {
78+ final ArangoPersistentEntity <?> persistentEntity = context
79+ .getPersistentEntity (property .getActualType ());
80+ final StringBuilder predicateBuilderArray = new StringBuilder ();
81+ for (Object item : (Iterable ) value ) {
82+ final StringBuilder predicateBuilderArrayItem = new StringBuilder ();
83+ traversePropertyTree (example , predicateBuilderArrayItem , bindVars , "" , fullJavaPath ,
84+ persistentEntity , item , "CURRENT" );
85+ if (predicateBuilderArray .length () > 0 ) {
86+ predicateBuilderArray .append (" OR " );
87+ }
88+ predicateBuilderArray .append (predicateBuilderArrayItem .toString ());
89+ }
90+ final String delimiter = example .getMatcher ().isAllMatching () ? " AND " : " OR " ;
91+ if (predicateBuilder .length () > 0 ) {
92+ predicateBuilder .append (delimiter );
93+ }
94+ String clause = String .format ("LENGTH(%s.%s[* FILTER %s ])>0" , bindEntintyName , property .getName (),
95+ predicateBuilderArray .toString ());
96+ predicateBuilder .append (clause );
97+
98+ } else if (property .isEntity () && value != null ) {
7499 final ArangoPersistentEntity <?> persistentEntity = context .getPersistentEntity (property .getType ());
75100 traversePropertyTree (example , predicateBuilder , bindVars , fullPath , fullJavaPath , persistentEntity ,
76- value );
101+ value , bindEntintyName );
77102 } else if (!example .getMatcher ().isIgnoredPath (fullJavaPath ) && (value != null
78103 || example .getMatcher ().getNullHandler ().equals (ExampleMatcher .NullHandler .INCLUDE ))) {
79- addPredicate (example , predicateBuilder , bindVars , fullPath , fullJavaPath , value );
104+ addPredicate (example , predicateBuilder , bindVars , fullPath , fullJavaPath , value , bindEntintyName );
80105 }
81106 });
82107
@@ -91,20 +116,22 @@ private void traversePropertyTree(
91116 final ArangoPersistentEntity <?> persistentEntity = context .getPersistentEntity (property .getType ());
92117 final PersistentPropertyAccessor <?> associatedAccessor = persistentEntity .getPropertyAccessor (value );
93118 final Object idValue = associatedAccessor .getProperty (persistentEntity .getIdProperty ());
94-
95- String refIdValue = String .format ("%s/%s" , persistentEntity .getCollection (), idValue );
96- addPredicate (example , predicateBuilder , bindVars , fullPath , fullJavaPath , refIdValue );
119+ String refIdValue = null ;
120+ if (property .getRef ().isPresent ()) {
121+ final Optional <ReferenceResolver <Annotation >> resolver = resolverFactory
122+ .getReferenceResolver (property .getRef ().get ());
123+ refIdValue = resolver .get ().write (value , persistentEntity , idValue , property .getRef ().get ());
124+ } else {
125+ refIdValue = String .format ("%s/%s" , persistentEntity .getCollection (), idValue );
126+ }
127+ addPredicate (example , predicateBuilder , bindVars , fullPath , fullJavaPath , refIdValue , bindEntintyName );
97128 }
98129 });
99130 }
100131
101- private void addPredicate (
102- final Example <T > example ,
103- final StringBuilder predicateBuilder ,
104- final Map <String , Object > bindVars ,
105- final String fullPath ,
106- final String fullJavaPath ,
107- Object value ) {
132+ private void addPredicate (final Example <T > example , final StringBuilder predicateBuilder ,
133+ final Map <String , Object > bindVars , final String fullPath , final String fullJavaPath , Object value ,
134+ final String bindEntintyName ) {
108135 final String delimiter = example .getMatcher ().isAllMatching () ? " AND " : " OR " ;
109136 if (predicateBuilder .length () > 0 ) {
110137 predicateBuilder .append (delimiter );
@@ -117,7 +144,7 @@ private void addPredicate(
117144 value = specifier .transformValue (Optional .of (value )).orElse (null );
118145 }
119146 if (value == null ) {
120- clause = String .format ("e .%s == null" , fullPath );
147+ clause = String .format ("%s .%s == null" , bindEntintyName , fullPath );
121148 } else if (String .class .isAssignableFrom (value .getClass ())) {
122149 final boolean ignoreCase = specifier == null ? example .getMatcher ().isIgnoreCaseEnabled ()
123150 : (specifier .getIgnoreCase () == null ? false : specifier .getIgnoreCase ());
@@ -127,10 +154,10 @@ private void addPredicate(
127154 : specifier .getStringMatcher ();
128155 final String string = (String ) value ;
129156 if (stringMatcher == ExampleMatcher .StringMatcher .REGEX ) {
130- clause = String .format ("REGEX_TEST(e .%s, @%s, %b)" , fullPath , binding , ignoreCase );
131- } else {
132- clause = String .format ("LIKE(e .%s, @%s, %b)" , fullPath , binding , ignoreCase );
133- }
157+ clause = String .format ("REGEX_TEST(%s .%s, @%s, %b)" , bindEntintyName , fullPath , binding , ignoreCase );
158+ } else {
159+ clause = String .format ("LIKE(%s .%s, @%s, %b)" , bindEntintyName , fullPath , binding , ignoreCase );
160+ }
134161 switch (stringMatcher ) {
135162 case STARTING :
136163 value = escape (string ) + "%" ;
@@ -142,16 +169,16 @@ private void addPredicate(
142169 value = "%" + escape (string ) + "%" ;
143170 break ;
144171 case REGEX :
145- value = escape (string );
146- break ;
172+ value = escape (string );
173+ break ;
147174 case DEFAULT :
148175 case EXACT :
149176 default :
150177 value = escape (string );
151178 break ;
152179 }
153180 } else {
154- clause = "e." + fullPath + " == @" + binding ;
181+ clause = String . format ( "%s.%s == @%s" , bindEntintyName , fullPath , binding ) ;
155182 }
156183 predicateBuilder .append (clause );
157184 if (value != null ) {
0 commit comments