diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java index 4e0571350..5aa10ca36 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java @@ -18,6 +18,7 @@ */ package org.apache.openjpa.kernel.exps; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -27,6 +28,7 @@ import java.util.Set; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.lib.util.StringDistance; import org.apache.openjpa.lib.util.Localizer.Message; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; @@ -280,9 +282,14 @@ public abstract class AbstractExpressionBuilder { FieldMetaData fmd = meta.getField(field); if (fmd == null) { Object val = traverseStaticField(meta.getDescribedType(), field); - if (val == null) + if (val == null) { + String[] all = meta.getFieldNames(); + Class cls = meta.getDescribedType(); throw parseException(EX_USER, "no-field", - new Object[]{ meta.getDescribedType(), field }, null); + new Object[] {field, cls.getSimpleName(), + StringDistance.getClosestLevenshteinDistance(field, all), + cls.getName(), Arrays.toString(all)}, null); + } return factory.newLiteral(val, Literal.TYPE_UNKNOWN); } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java index ff2810183..89c26192d 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java @@ -26,6 +26,7 @@ import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -2375,4 +2376,29 @@ public class ClassMetaData _cacheTimeout = Integer.MIN_VALUE; } } + + /** + * Utility method to get names of all fields including the superclasses' + * sorted in lexical order. + */ + public String[] getFieldNames() { + return toNames(getFields()); + } + + /** + * Utility method to get names of all declared fields excluding the + * superclasses' sorted in lexical order. + */ + public String[] getDeclaredFieldNames() { + return toNames(getDeclaredFields()); + } + + String[] toNames(FieldMetaData[] fields) { + List result = new ArrayList(); + for (FieldMetaData fmd : fields) { + result.add(fmd.getName()); + } + Collections.sort(result); + return result.toArray(new String[result.size()]); + } } diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties index f1da81f10..4dd1b3e61 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties @@ -28,9 +28,10 @@ no-alias: The alias "{0}" was not declared in the statement (declared \ cant-resolve-type: The entity "{0}" cannot be resolved; please ensure that \ the entity name has been declared for the class. not-identifer: The specified node ("{0}") is not a valid identifier. -no-field: No field named "{1}" in class "{0}". +no-field: No field named "{0}" in "{1}". Did you mean "{2}"? Expected one of \ + the available field names in "{3}": "{4}". unaccessible-field: The field named "{1}" in class "{0}" could not be accessed. -multi-children: Expression "{0}" does not allow mutliple children ("{1}"). +multi-children: Expression "{0}" does not allow multiple children ("{1}"). no-children: Expression "{0}" requires at least one child. unknown-comp: Unknown comparison operator "{0}". wrong-child-count: Wrong number of arguments to expression \