Skip to content

Commit

Permalink
[incubator-kie-issues#1370] Working. Implemented tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriele-Cardosi committed Jul 11, 2024
1 parent 3d971b6 commit 7d55494
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* "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
* 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
Expand Down Expand Up @@ -167,7 +167,8 @@ protected CandidateMethod getCandidateMethod(EvaluationContext ctx, Object[] ori
// first, look for exact matches
for (Method m : invokeMethods) {

Object[] adaptedInput = BaseFEELFunctionHelper.getAdjustedParametersForMethod(ctx, originalInput, isNamedParams, m);
Object[] adaptedInput = BaseFEELFunctionHelper.getAdjustedParametersForMethod(ctx, originalInput,
isNamedParams, m);
if (adaptedInput == null) {
// incompatible method
continue;
Expand All @@ -185,32 +186,9 @@ protected CandidateMethod getCandidateMethod(EvaluationContext ctx, Object[] ori
if (candidate == null) {
candidate = cm;
} else if (cm.getScore() > candidate.getScore()) {
candidate = cm;
}
candidate = cm;
}


// CandidateMethod cm = new CandidateMethod(adaptedInput);
// cm.setActualMethod(m);
// if (candidate == null) {
// candidate = cm;
// } else {
// if (cm.getScore() > candidate.getScore()) {
// candidate = cm;
// } else if (cm.getScore() == candidate.getScore()) {
// if (isNamedParams && ScoreHelper.nullCount(cm.actualParams) < ScoreHelper.nullCount(candidate.actualParams)) {
// candidate = cm; // `cm` narrower for named parameters without need of passing nulls.
// } else if (candidate.getActualMethod().getParameterTypes().length == 1
// && cm.getActualMethod().getParameterTypes().length == 1
// && candidate.getActualMethod().getParameterTypes()[0].equals(Object.class)
// && !cm.getActualMethod().getParameterTypes()[0].equals(Object.class)) {
// candidate = cm; // `cm` is more narrowed, hence reflect `candidate` to be now `cm`.
// }
// } else {
// // do nothing.
// }
// }
// }
}
return candidate;
}

Expand Down Expand Up @@ -239,7 +217,6 @@ protected static class CandidateMethod {

private Method actualMethod = null;
private Object[] actualParams;
private Class[] actualClasses = null;
private int score;

public CandidateMethod(Method actualMethod, int score, Object[] actualParams) {
Expand All @@ -248,50 +225,12 @@ public CandidateMethod(Method actualMethod, int score, Object[] actualParams) {
this.actualParams = actualParams;
}

// public CandidateMethod(Object[] actualParams) {
// this.actualParams = actualParams;
// populateActualClasses();
// }
//
// private void calculateScore() {
// if (actualClasses.length > 0 && actualClasses[actualClasses.length - 1] != null && actualClasses[actualClasses.length - 1].isArray()) {
// score = 1;
// } else {
// score = 10;
// }
// }

public Method getActualMethod() {
return actualMethod;
}

// public void setActualMethod(Method actualMethod) {
// this.actualMethod = actualMethod;
// calculateScore();
// }
//
// public Object[] getActualParams() {
// return actualParams;
// }
//
// public void setActualParams(Object[] actualParams) {
// this.actualParams = actualParams;
// populateActualClasses();
// }

private void populateActualClasses() {
this.actualClasses =
Stream.of(this.actualParams).map(p -> p != null ? p.getClass() : null).toArray(Class[]::new);
}

public Class[] getActualClasses() {
return actualClasses;
}

public int getScore() {
return score;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
* <p>
* Conditions considered (from most to less relevant):
* Condition Score
* 1. last input not array -> 100000
* 1. last parameter not array -> 10000
* 2. number of parameters -> 1000
* 3. type identity of all parameters -> -> weighted value of matching parameters and values 0-1000
Expand All @@ -48,6 +49,7 @@ public class ScoreHelper {

private static final List<Function<Compares, Integer>> SCORER_LIST;

static int lastInputNotArrayNotArrayScore = 100000;
static int lastParameterNotArrayScore = 10000;
static int numberOfParametersScore = 1000;
static int coercedToVarargsScore = -10;
Expand All @@ -73,7 +75,7 @@ public class ScoreHelper {
compares.originalInput[i] != null &&
compares.originalInput[i] instanceof EvaluationContext) {
// Do not consider EvaluationContext for score
matchedEvaluationContext +=1;
matchedEvaluationContext += 1;
continue;
}
// In this case, we switch the parameter comparison, ignoring the first parameterType
Expand All @@ -82,54 +84,81 @@ public class ScoreHelper {
Object originalValue = compares.originalInput[i];
if (expectedType.equals(Object.class)) {
// parameter type is Object
counter +=1;
counter += 1;
}
if (originalValue == null) {
// null value has a potential match
counter +=1;
counter += 1;
} else if (!(expectedType.isInstance(originalValue))) {
// do not count it
continue;
} else if (expectedType.isInterface() || expectedType.equals(originalValue.getClass()) || expectedType.isAssignableFrom(originalValue.getClass())) {
} else if (!(expectedType.equals(Object.class)) &&
(expectedType.isInterface() ||
expectedType.equals(originalValue.getClass()) ||
expectedType.isAssignableFrom(originalValue.getClass()))) {
counter += 2;
}
logger.trace("typeIdentityOfParameters {} {} -> {}", expectedType, originalValue, counter);
}
int elementsToConsider = index - matchedEvaluationContext;
int toReturn = counter > 0 ? Math.round(((float) counter/elementsToConsider) * 500) : 0;
int toReturn = counter > 0 ? Math.round(((float) counter / elementsToConsider) * 500) : 0;
logger.trace("typeIdentityOfParameters {} -> {}", compares, toReturn);
return toReturn;
};

static final Function<Compares, Integer> lastInputNotArray =
compares -> {
int toReturn = isLastInputArray(compares.adaptedInput) ? 0 :
lastInputNotArrayNotArrayScore;
logger.trace("lastInputNotArray {} -> {}", compares, toReturn);
return toReturn;
};

static boolean isLastInputArray(Object[] adaptedInput) {
return adaptedInput != null &&
adaptedInput.length > 0 &&
adaptedInput[adaptedInput.length - 1] != null &&
adaptedInput[adaptedInput.length - 1].getClass().isArray();
}

static final Function<Compares, Integer> lastParameterNotArray =
compares -> {
int toReturn = compares.adaptedInput.length > 0 &&
compares.adaptedInput[compares.adaptedInput.length - 1] != null &&
!compares.adaptedInput[compares.adaptedInput.length - 1].getClass().isArray() ? lastParameterNotArrayScore : 0;
int toReturn = isLastParameterArray(compares.parameterTypes) ? 0 :
lastParameterNotArrayScore;
logger.trace("lastParameterNotArray {} -> {}", compares, toReturn);
return toReturn;
};

static boolean isLastParameterArray(Class<?>[] parameterTypes) {
return parameterTypes != null &&
parameterTypes.length > 0 &&
parameterTypes[parameterTypes.length - 1] != null &&
parameterTypes[parameterTypes.length - 1].isArray();
}

static final Function<Compares, Integer> coercedToVarargs =
compares -> {
Object[] amendedOriginalInput = compares.originalInput != null ? Arrays.stream(compares.originalInput)
Object[] amendedOriginalInput = compares.originalInput != null ? Arrays.stream(compares.originalInput)
.filter(o -> !(o instanceof EvaluationContext)).toArray() : new Object[0];
Object[] amendedAdaptedInput = compares.adaptedInput != null ? Arrays.stream(compares.adaptedInput)
Object[] amendedAdaptedInput = compares.adaptedInput != null ? Arrays.stream(compares.adaptedInput)
.filter(o -> !(o instanceof EvaluationContext)).toArray() : new Object[0];
int toReturn = 0;
if (amendedOriginalInput.length >= amendedAdaptedInput.length &&
amendedAdaptedInput.length == 1 &&
isCoercedToVarargs(amendedOriginalInput[amendedOriginalInput.length - 1], amendedAdaptedInput[0])) {
isCoercedToVarargs(amendedOriginalInput[amendedOriginalInput.length - 1],
amendedAdaptedInput[0])) {
toReturn = coercedToVarargsScore;
}
logger.trace("coercedToVarargs {} -> {}", compares, toReturn);
return toReturn;
};

static boolean isCoercedToVarargs(Object originalInput, Object adaptedInput) {
boolean isOriginalInputCandidate = originalInput == null || !originalInput.getClass().equals(Object.class.arrayType());
boolean isAdaptedInputCandidate = adaptedInput != null && adaptedInput.getClass().equals(Object.class.arrayType());
return isOriginalInputCandidate && isAdaptedInputCandidate;
boolean isOriginalInputCandidate =
originalInput == null || !originalInput.getClass().equals(Object.class.arrayType());
boolean isAdaptedInputCandidate =
adaptedInput != null && adaptedInput.getClass().equals(Object.class.arrayType());
return isOriginalInputCandidate && isAdaptedInputCandidate;
}

static final Function<Compares, Integer> nullCounts =
Expand All @@ -141,15 +170,16 @@ static boolean isCoercedToVarargs(Object originalInput, Object adaptedInput) {

static {
SCORER_LIST = new ArrayList<>();
SCORER_LIST.add(lastInputNotArray);
SCORER_LIST.add(lastParameterNotArray);
SCORER_LIST.add(numberOfParameters);
SCORER_LIST.add(typeIdentityOfParameters);
SCORER_LIST.add(lastParameterNotArray);
SCORER_LIST.add(coercedToVarargs);
SCORER_LIST.add(nullCounts);
}

static int score(Compares toScore) {
int toReturn = SCORER_LIST.stream()
int toReturn = SCORER_LIST.stream()
.map(comparesIntegerFunction ->
comparesIntegerFunction.apply(toScore))
.reduce(0, Integer::sum);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,37 +67,35 @@ void adjustByCoercion() {
retrieved = BaseFEELFunctionHelper.adjustByCoercion(parameterTypes, actualParams);
assertEquals(actualParams, retrieved);

// coercing null value to not-list type
// not coercing null value to not-list type
actualParam = null;
actualParams = new Object[]{actualParam};
retrieved = BaseFEELFunctionHelper.adjustByCoercion(parameterTypes, actualParams);
assertEquals(actualParams, retrieved);

// coercing value to singleton list
// not coercing null value to singleton list
parameterTypes = new Class[]{List.class};
retrieved = BaseFEELFunctionHelper.adjustByCoercion(parameterTypes, actualParams);
assertNotEquals(actualParams, retrieved);
assertNotNull(retrieved);
assertEquals(1, retrieved.length);
assertNotNull(retrieved[0]);
assertThat(retrieved[0]).isInstanceOf(List.class);
List retrievedList = (List) retrieved[0];
assertEquals(1, retrievedList.size());
assertEquals(actualParam, retrievedList.get(0));
assertEquals(actualParams, retrieved);

// coercing null value to singleton list
actualParam = null;
// coercing not-null value to singleton list
actualParam = "StringA";
actualParams = new Object[]{actualParam};
retrieved = BaseFEELFunctionHelper.adjustByCoercion(parameterTypes, actualParams);
assertNotEquals(actualParams, retrieved);
assertNotNull(retrieved);
assertNotEquals(actualParams, retrieved);
assertEquals(1, retrieved.length);
assertNotNull(retrieved[0]);
assertThat(retrieved[0]).isInstanceOf(List.class);
retrievedList = (List) retrieved[0];
List retrievedList = (List) retrieved[0];
assertEquals(1, retrievedList.size());
assertEquals(actualParam, retrievedList.get(0));

// coercing null value to array: fails
parameterTypes = new Class[]{Object.class.arrayType()};
retrieved = BaseFEELFunctionHelper.adjustByCoercion(parameterTypes, actualParams);
assertNull(retrieved);

// coercing one object to different type: fails
actualParam = 45;
parameterTypes = new Class[]{String.class};
Expand Down
Loading

0 comments on commit 7d55494

Please sign in to comment.