Hi Jurgen, I support the idea behind this API. Let's discuss the shape of it though.
In DFLib (a completely unrelated library that I am working on), we solved a similar problem with a more generic "map(..)" method that performs an arbitrary transformation on the object, that can include condition checking: https://github.com/dflib/dflib/blob/main/dflib/src/main/java/org/dflib/DataFrame.java#L214 So how about this : ObjectSelect.query(A.class).map(q -> c ? q.and(exp) : q); ObjectSelect.query(A.class).map(q -> c ? q.and(exp1) : q.and(exp2)); Cheers, Andrus > On Jul 3, 2024, at 7:32 AM, Jurgen Doll <jur...@ivoryemr.co.za> wrote: > > Hi All > > I really like the fluent style in Cayenne 4. > > However I found that sometimes the fluent style in my code needs to be > interrupted if some condition has to be tested before configuring the select > any further, which then breaks the nice flow of code. > > So I suggest adding the following API to ObjectSelect and to Expression > that'll smooth this over: > > Add to ObjectSelect: > /** > * Conditionally append/chain the provided operation. > * @param condition if true then accept is invoked on the Consumer > parameter > * @param op provides the ObjectSelect to be modified if condition is true > * @return > */ > public ObjectSelect addIf( boolean condition, Consumer> op ) > { > if ( condition ) op.accept( this ); > return this; > } > Examples from my code base: > .addIf( yearRange != null, q -> q.where( APPOINTMENT_DATE.gt( yearRange ) > ) ) > > > .addIf( includePublic, q -> q.or( createDateRangeExpression( 9999 ) ) ) > > > .addIf( withAttachments, q -> q.prefetch( Message.ATTACHMENTS.joint() ) ) > > ---------------------- > > Add to Expression: > /** > * Conditionally append the provided operation to the current expression. > * @param condition if true then apply is invoked on the UnaryOperator > parameter > * @param op provides the expression to be modified if condition is true > * @return > */ > public Expression addIf( boolean condition, UnaryOperator op ) > { > return (condition) ? op.apply( this ) : this; > } > Examples from my code base: > DefaultValue.USER.eq( userId ).andExp( DefaultValue.VALUE.ne( "" ) ) > .addIf( keyName != null, exp -> exp.andExp( DefaultValue.NAME.eq( keyName > ) ) ) > > > ExpressionFactory.matchExp( PatientNew.DATE_OF_BIRTH_PROPERTY, dob ) > .addIf( idNo.length() > 6, exp -> exp.andExp( PatientNew.ID_NO.like( > idNo.substring(0,6)+"%" ) ) ) > > > User.FIRSTNAME.eq( userParts[0] ) > .addIf( userParts.length == 2, exp -> exp.andExp( User.SURNAME.eq( > userParts[1] ) ) ) > > > AppointmentSms.APPOINTMENT_DATE.eq( aptDate ) > .addIf( marketing, q -> q.andExp( AppointmentSms.MARKETING.eq( true ) ) ) > > What do you guys think ? > > I can submit a PR if it passes as a good feature to add. > The name of the method can be changed if anyone has a better suggestion. > > Thanks, regards > Jurgen