Add LIKE and Contains condition to Criteria
Signed-off-by: WimVelzeboer <wimvelzeboer@protonmail.com>
This commit is contained in:
@@ -33,8 +33,15 @@ public with sharing class fflib_Comparator
|
|||||||
|
|
||||||
public static Boolean compareTo(Object object1, fflib_Operator operator, Object object2)
|
public static Boolean compareTo(Object object1, fflib_Operator operator, Object object2)
|
||||||
{
|
{
|
||||||
Integer result = compare(object1, object2);
|
if (operator == fflib_Operator.LIKEx)
|
||||||
|
{
|
||||||
|
String value1 = String.valueOf(object1);
|
||||||
|
String value2 = String.valueOf(object2);
|
||||||
|
if (value1 == null || value2 == null) return false;
|
||||||
|
return value1.contains(value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer result = compare(object1, object2);
|
||||||
if (operator == fflib_Operator.EQUALS && result == 0)
|
if (operator == fflib_Operator.EQUALS && result == 0)
|
||||||
return true;
|
return true;
|
||||||
else if (operator == fflib_Operator.NOT_EQUALS && result != 0)
|
else if (operator == fflib_Operator.NOT_EQUALS && result != 0)
|
||||||
|
|||||||
@@ -323,6 +323,32 @@ public virtual with sharing class fflib_Criteria
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a criteria checking if a fields value contains the given value
|
||||||
|
*
|
||||||
|
* @param field The sObjectField to evaluate
|
||||||
|
* @param value The value to be compared to the fields value
|
||||||
|
*
|
||||||
|
* @return An instance of itself to enable method chaining
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* new fflib_Criteria()
|
||||||
|
* .equalTo(Account.Name, 'Example')
|
||||||
|
*
|
||||||
|
* Evaluates:
|
||||||
|
* SOQL
|
||||||
|
* Name LIKE '%Example%'
|
||||||
|
*
|
||||||
|
* Condition
|
||||||
|
* 'My Condition Example'.contains('Example')
|
||||||
|
*/
|
||||||
|
public virtual fflib_Criteria contains(Schema.SObjectField field, Object value)
|
||||||
|
{
|
||||||
|
evaluators.add(new FieldEvaluator(field, fflib_Operator.LIKEx, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an equal to criteria comparing a fields value to a given value
|
* Add an equal to criteria comparing a fields value to a given value
|
||||||
*
|
*
|
||||||
@@ -820,15 +846,15 @@ public virtual with sharing class fflib_Criteria
|
|||||||
else if (operator == fflib_Operator.GREATER_THAN_OR_EQUAL_TO)
|
else if (operator == fflib_Operator.GREATER_THAN_OR_EQUAL_TO)
|
||||||
return '>=';
|
return '>=';
|
||||||
else if (operator == fflib_Operator.LIKEx)
|
else if (operator == fflib_Operator.LIKEx)
|
||||||
return 'LIKE';
|
return ' LIKE ';
|
||||||
else if (operator == fflib_Operator.INx)
|
else if (operator == fflib_Operator.INx)
|
||||||
return 'IN';
|
return ' IN ';
|
||||||
else if (operator == fflib_Operator.NOT_IN)
|
else if (operator == fflib_Operator.NOT_IN)
|
||||||
return 'NOT IN';
|
return ' NOT IN ';
|
||||||
else if (operator == fflib_Operator.INCLUDES)
|
else if (operator == fflib_Operator.INCLUDES)
|
||||||
return 'INCLUDES';
|
return ' INCLUDES ';
|
||||||
else if (operator == fflib_Operator.EXCLUDES)
|
else if (operator == fflib_Operator.EXCLUDES)
|
||||||
return 'EXCLUDES';
|
return ' EXCLUDES ';
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -875,7 +901,9 @@ public virtual with sharing class fflib_Criteria
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new CriteriaException(
|
throw new CriteriaException(
|
||||||
'invalid value; value must a primitive type (String|Id|Boolean|Integer|Long|Double|Decimal|Date|Datetime)'
|
String.format(
|
||||||
|
'invalid value \'{0}\'; value must a primitive type (String|Id|Boolean|Integer|Long|Double|Decimal|Date|Datetime)',
|
||||||
|
new List<String> {String.valueOf(value)})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,6 +934,52 @@ public virtual with sharing class fflib_Criteria
|
|||||||
String toSOQL();
|
String toSOQL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private abstract class ToSOQL
|
||||||
|
{
|
||||||
|
protected String toSOQL(Schema.SObjectField sObjectField, fflib_Operator operator, Object value)
|
||||||
|
{
|
||||||
|
return toSOQL(sObjectField, operator, toLiteral(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String toSOQL(String fieldName, fflib_Operator operator, Object value)
|
||||||
|
{
|
||||||
|
return toSOQL(fieldName, operator, toLiteral(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String toSOQL(Schema.SObjectField sObjectField, fflib_Operator operator, String value)
|
||||||
|
{
|
||||||
|
return toSOQL(sObjectField.getDescribe().getName(), operator, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String toSOQL(String fieldName, fflib_Operator operator, String value)
|
||||||
|
{
|
||||||
|
if (operator == fflib_Operator.LIKEx)
|
||||||
|
return toLikeSOQL(fieldName, operator, value);
|
||||||
|
else
|
||||||
|
return toNonLikeSOQL(fieldName, operator, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toLikeSOQL(String fieldName, fflib_Operator operator, String value)
|
||||||
|
{
|
||||||
|
if (value.startsWith('\'')) value = value.right(value.length() - 1);
|
||||||
|
if (value.endsWith('\'')) value = value.left(value.length() - 1);
|
||||||
|
return toNonLikeSOQL(fieldName, operator, '\'%' + value + '%\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String toNonLikeSOQL(String fieldName, fflib_Operator operator, String value)
|
||||||
|
{
|
||||||
|
return String.join(
|
||||||
|
new List<String>
|
||||||
|
{
|
||||||
|
fieldName,
|
||||||
|
operatorToString(operator),
|
||||||
|
value
|
||||||
|
},
|
||||||
|
''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic criteria handler for comparing against sets
|
* Generic criteria handler for comparing against sets
|
||||||
*/
|
*/
|
||||||
@@ -935,7 +1009,7 @@ public virtual with sharing class fflib_Criteria
|
|||||||
public String toSOQL()
|
public String toSOQL()
|
||||||
{
|
{
|
||||||
return String.format(
|
return String.format(
|
||||||
'{0} {1} {2}',
|
'{0}{1}{2}',
|
||||||
new List<String>
|
new List<String>
|
||||||
{
|
{
|
||||||
this.sObjectField.getDescribe().getName(),
|
this.sObjectField.getDescribe().getName(),
|
||||||
@@ -949,7 +1023,7 @@ public virtual with sharing class fflib_Criteria
|
|||||||
/**
|
/**
|
||||||
* Generic field Evaluator
|
* Generic field Evaluator
|
||||||
*/
|
*/
|
||||||
private class FieldEvaluator implements Evaluator
|
private class FieldEvaluator extends ToSOQL implements Evaluator
|
||||||
{
|
{
|
||||||
private Schema.SObjectField sObjectField;
|
private Schema.SObjectField sObjectField;
|
||||||
private Object value;
|
private Object value;
|
||||||
@@ -974,19 +1048,11 @@ public virtual with sharing class fflib_Criteria
|
|||||||
|
|
||||||
public String toSOQL()
|
public String toSOQL()
|
||||||
{
|
{
|
||||||
return String.join(
|
return toSOQL(this.sObjectField, this.operator, this.value);
|
||||||
new List<String>
|
|
||||||
{
|
|
||||||
this.sObjectField.getDescribe().getName(),
|
|
||||||
operatorToString(this.operator),
|
|
||||||
toLiteral(this.value)
|
|
||||||
},
|
|
||||||
''
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class AbstractRelatedFieldEvaluator implements Evaluator
|
private abstract class AbstractRelatedFieldEvaluator extends ToSOQL implements Evaluator
|
||||||
{
|
{
|
||||||
protected String fieldName;
|
protected String fieldName;
|
||||||
protected fflib_Operator operator;
|
protected fflib_Operator operator;
|
||||||
@@ -1035,15 +1101,7 @@ public virtual with sharing class fflib_Criteria
|
|||||||
|
|
||||||
public String toSOQL()
|
public String toSOQL()
|
||||||
{
|
{
|
||||||
return String.join(
|
return toSOQL(this.fieldName, operator, this.value);
|
||||||
new List<String>
|
|
||||||
{
|
|
||||||
this.fieldName,
|
|
||||||
operatorToString(this.operator),
|
|
||||||
toLiteral(this.value)
|
|
||||||
},
|
|
||||||
''
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1071,7 +1129,7 @@ public virtual with sharing class fflib_Criteria
|
|||||||
public String toSOQL()
|
public String toSOQL()
|
||||||
{
|
{
|
||||||
return String.format(
|
return String.format(
|
||||||
'{0} {1} {2}',
|
'{0}{1}{2}',
|
||||||
new List<String>
|
new List<String>
|
||||||
{
|
{
|
||||||
this.fieldName,
|
this.fieldName,
|
||||||
|
|||||||
@@ -79,6 +79,30 @@ private with sharing class fflib_CriteriaTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IsTest
|
||||||
|
static void itShouldEvaluateAnContainsCondition()
|
||||||
|
{
|
||||||
|
fflib_Criteria criteria = new fflib_Criteria()
|
||||||
|
.contains(Account.Name, A_STRING);
|
||||||
|
System.assert(criteria.evaluate(new Account(Name = SAME_STRING)));
|
||||||
|
System.assert(criteria.evaluate(new Account(Name = 'prefix ' + SAME_STRING)));
|
||||||
|
System.assert(criteria.evaluate(new Account(Name = SAME_STRING + ' suffix')));
|
||||||
|
System.assert(criteria.evaluate(new Account(Name = 'prefix ' + SAME_STRING + ' suffix')));
|
||||||
|
System.assertEquals('Name LIKE \'%' + A_STRING + '%\'', criteria.toSOQL());
|
||||||
|
}
|
||||||
|
|
||||||
|
@IsTest
|
||||||
|
static void itShouldEvaluateAnContainsCondition_nullField()
|
||||||
|
{
|
||||||
|
fflib_Criteria criteria = new fflib_Criteria()
|
||||||
|
.contains(Account.Name, null);
|
||||||
|
System.assert(false == criteria.evaluate(new Account(Name = SAME_STRING)));
|
||||||
|
System.assert(false == criteria.evaluate(new Account(Name = 'prefix ' + SAME_STRING)));
|
||||||
|
System.assert(false == criteria.evaluate(new Account(Name = SAME_STRING + ' suffix')));
|
||||||
|
System.assert(false == criteria.evaluate(new Account(Name = 'prefix ' + SAME_STRING + ' suffix')));
|
||||||
|
System.assertEquals('Name LIKE \'%null%\'', criteria.toSOQL());
|
||||||
|
}
|
||||||
|
|
||||||
@IsTest
|
@IsTest
|
||||||
static void itShouldEvaluateAnEqualsToCondition()
|
static void itShouldEvaluateAnEqualsToCondition()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user