/** * Snoops through the declaring class and all parents looking for methods * * <ul> * <li><code>public String getMessage(java.lang.String)</code> * <li><code>public String getMessage(java.lang.String, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[])</code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.List)</code> * <li><code>public String getMessage(java.lang.String, java.util.List, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.util.Map)</code> * <li><code>public String getMessage(java.lang.String, java.util.Map, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.lang.String)</code> * <li><code>public String getMessage(java.lang.String, java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.lang.String) * </code> * <li><code> * public String getMessage(java.lang.String, java.lang.Object[], java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.List, java.lang.String)</code> * <li><code> * public String getMessage(java.lang.String, java.util.List, java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.Map, java.lang.String)</code> * <li><code> * public String getMessage(java.lang.String, java.util.Map, java.lang.String, java.util.Locale) * </code> * </ul> * * If any are defined all must be defined or a compilation error results. * * @param declaringClass the class to search * @param sourceUnit the source unit, for error reporting. {@code @NotNull}. * @return true if property change support should be added */ protected static boolean needsMessageSource(ClassNode declaringClass, SourceUnit sourceUnit) { boolean found = false; ClassNode consideredClass = declaringClass; while (consideredClass != null) { for (MethodNode method : consideredClass.getMethods()) { // just check length, MOP will match it up found = method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 1; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 2; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 3; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 4; if (found) return false; } consideredClass = consideredClass.getSuperClass(); } if (found) { sourceUnit .getErrorCollector() .addErrorAndContinue( new SimpleMessage( "@MessageSourceAware cannot be processed on " + declaringClass.getName() + " because some but not all of variants of getMessage() were declared in the current class or super classes.", sourceUnit)); return false; } return true; }
public static void addResourceLocatorIfNeeded(SourceUnit source, ClassNode classNode) { if (needsMessageSource(classNode, source)) { if (LOG.isDebugEnabled()) { LOG.debug("Injecting " + ResourceLocator.class.getName() + " into " + classNode.getName()); } apply(classNode); } }
private FieldNode getKeyField(ClassNode target) { List<FieldNode> annotatedFields = getAnnotatedFieldsOfHierarchy(target, KEY_ANNOTATION); if (annotatedFields.isEmpty()) return null; if (annotatedFields.size() > 1) { addCompileError( String.format( "Found more than one key fields, only one is allowed in hierarchy (%s, %s)", getQualifiedName(annotatedFields.get(0)), getQualifiedName(annotatedFields.get(1))), annotatedFields.get(0)); return null; } FieldNode result = annotatedFields.get(0); if (!result.getType().equals(ClassHelper.STRING_TYPE)) { addCompileError( String.format( "Key field '%s' must be of type String, but is '%s' instead", result.getName(), result.getType().getName()), result); return null; } ClassNode ancestor = ASTHelper.getHighestAncestorDSLObject(target); if (target.equals(ancestor)) return result; FieldNode firstKey = getKeyField(ancestor); if (firstKey == null) { addCompileError( String.format( "Inconsistent hierarchy: Toplevel class %s has no key, but child class %s defines '%s'.", ancestor.getName(), target.getName(), result.getName()), result); return null; } return result; }
private void createMapOfDSLObjectMethods( FieldNode fieldNode, ClassNode keyType, ClassNode elementType) { if (getKeyField(elementType) == null) { addCompileError( String.format( "Value type of map %s (%s) has no key field", fieldNode.getName(), elementType.getName()), fieldNode); return; } MethodBuilder.createPublicMethod(fieldNode.getName()) .closureParam("closure") .assignS(propX(varX("closure"), "delegate"), varX("this")) .assignS( propX(varX("closure"), "resolveStrategy"), propX(classX(ClassHelper.CLOSURE_TYPE), "DELEGATE_FIRST")) .callMethod("closure", "call") .addTo(annotatedClass); String methodName = getElementNameForCollectionField(fieldNode); String targetOwner = getOwnerFieldName(elementType); if (!ASTHelper.isAbstract(elementType)) { MethodBuilder.createPublicMethod(methodName) .returning(elementType) .namedParams("values") .param(keyType, "key") .delegatingClosureParam(elementType) .declareVariable("created", callX(classX(elementType), "newInstance", args("key"))) .callMethod("created", "copyFromTemplate") .optionalAssignThisToPropertyS("created", targetOwner, targetOwner) .callMethod(fieldNode.getName(), "put", args(varX("key"), varX("created"))) .callMethod("created", "apply", args("values", "closure")) .callValidationOn("created") .doReturn("created") .addTo(annotatedClass); MethodBuilder.createPublicMethod(methodName) .returning(elementType) .param(keyType, "key") .delegatingClosureParam(elementType) .declareVariable("created", callX(classX(elementType), "newInstance", args("key"))) .callMethod("created", "copyFromTemplate") .optionalAssignThisToPropertyS("created", targetOwner, targetOwner) .callMethod(fieldNode.getName(), "put", args(varX("key"), varX("created"))) .callMethod("created", "apply", varX("closure")) .callValidationOn("created") .doReturn("created") .addTo(annotatedClass); } if (!isFinal(elementType)) { MethodBuilder.createPublicMethod(methodName) .returning(elementType) .namedParams("values") .classParam("typeToCreate", elementType) .param(keyType, "key") .delegatingClosureParam(elementType) .declareVariable("created", callX(varX("typeToCreate"), "newInstance", args("key"))) .callMethod("created", "copyFromTemplate") .callMethod(fieldNode.getName(), "put", args(varX("key"), varX("created"))) .optionalAssignThisToPropertyS("created", targetOwner, targetOwner) .callMethod("created", "apply", args("values", "closure")) .callValidationOn("created") .doReturn("created") .addTo(annotatedClass); MethodBuilder.createPublicMethod(methodName) .returning(elementType) .classParam("typeToCreate", elementType) .param(keyType, "key") .delegatingClosureParam(elementType) .declareVariable("created", callX(varX("typeToCreate"), "newInstance", args("key"))) .callMethod("created", "copyFromTemplate") .callMethod(fieldNode.getName(), "put", args(varX("key"), varX("created"))) .optionalAssignThisToPropertyS("created", targetOwner, targetOwner) .callMethod("created", "apply", varX("closure")) .callValidationOn("created") .doReturn("created") .addTo(annotatedClass); } //noinspection ConstantConditions MethodBuilder.createPublicMethod(methodName) .param(elementType, "value") .callMethod( fieldNode.getName(), "put", args(propX(varX("value"), getKeyField(elementType).getName()), varX("value"))) .optionalAssignThisToPropertyS("value", targetOwner, targetOwner) .addTo(annotatedClass); }