public void setProperty()

in src/main/java/groovy/lang/MetaClassImpl.java [2674:2819]


    public void setProperty(final Class sender, final Object object, final String name, Object newValue, final boolean useSuper, final boolean fromInsideClass) {

        //----------------------------------------------------------------------
        // handling of static
        //----------------------------------------------------------------------
        boolean isStatic = (theClass != Class.class && object instanceof Class);
        if (isStatic && object != theClass) {
            MetaClass mc = registry.getMetaClass((Class<?>) object);
            mc.getProperty(sender, object, name, useSuper, fromInsideClass);
            return;
        }

        checkInitalised();

        //----------------------------------------------------------------------
        // Unwrap wrapped values for now - the new MOP will handle them properly
        //----------------------------------------------------------------------
        if (newValue instanceof Wrapper) newValue = ((Wrapper) newValue).unwrap();

        MetaMethod method = null;
        Object[] arguments = null;

        //----------------------------------------------------------------------
        // setter
        //----------------------------------------------------------------------
        MetaProperty mp = getMetaProperty(sender, name, useSuper, isStatic);
        MetaProperty field = null;
        if (mp != null) {
            if (mp instanceof MetaBeanProperty) {
                MetaBeanProperty mbp = (MetaBeanProperty) mp;
                method = mbp.getSetter();
                MetaProperty f = mbp.getField();
                if (method != null || (f != null && !f.isFinal())) {
                    arguments = new Object[]{newValue};
                    field = f;
                }
            } else {
                field = mp;
            }
        }

        // check for a category method named like a setter
        if (!useSuper && !isStatic && !name.isEmpty() && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            var setterName = GroovyCategorySupport.getPropertyCategorySetterName(name);
            if (setterName != null) {
                MetaMethod categoryMethod = getCategoryMethodSetter(theClass, setterName, false);
                if (categoryMethod != null) {
                    method = categoryMethod;
                    arguments = new Object[]{newValue};
                }
            }
        }

        //----------------------------------------------------------------------
        // listener method
        //----------------------------------------------------------------------
        boolean ambiguousListener = false;
        if (method == null) {
            method = listeners.get(name);
            ambiguousListener = (method == AMBIGUOUS_LISTENER_METHOD);
            if (method != null && !ambiguousListener && newValue instanceof Closure) {
                // bean.name = { -> } is short for bean.addSomeListener({ -> });
                // where "name" derives from the SomeListener interface's method
                var listener = method.getParameterTypes()[0].getTheClass();
                Object proxy = Proxy.newProxyInstance(
                        listener.getClassLoader(),
                        new Class[]{listener},
                        new ConvertedClosure((Closure<?>) newValue, name));
                arguments = new Object[]{proxy};
                newValue = proxy;
            } else {
                method = null;
            }
        }

        //----------------------------------------------------------------------
        // field
        //----------------------------------------------------------------------
        if (method == null && field != null
                && (!isMap || isStatic // GROOVY-8065
                    || field.isPublic())) { // GROOVY-11367
            if (!field.isFinal()) {
                field.setProperty(object, newValue);
                return;
            } else {
                throw new ReadOnlyPropertyException(name, theClass); // GROOVY-5985
            }
        }

        //----------------------------------------------------------------------
        // generic set method
        //----------------------------------------------------------------------
        // check for a generic get method provided through a category
        if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            method = getCategoryMethodSetter(theClass, "set", true);
            if (method != null) arguments = new Object[]{name, newValue};
        }
        if (method == null && genericSetMethod != null && (genericSetMethod.isStatic() || !isStatic)) {
            arguments = new Object[]{name, newValue};
            method = genericSetMethod;
        }

        //----------------------------------------------------------------------
        // java.util.Map put method before non-public method -- see GROOVY-11367
        //----------------------------------------------------------------------
        if (isMap && !isStatic && !(method != null && method.isPublic())
                  && (mp == null || !mp.isPublic() || isSpecialProperty(name))) {
            ((Map) object).put(name, newValue);
            return;
        }

        //----------------------------------------------------------------------
        // executing the method
        //----------------------------------------------------------------------
        if (method != null) {
            if (arguments.length == 1) {
                newValue = DefaultTypeTransformation.castToType(
                        newValue,
                        method.getParameterTypes()[0].getTheClass());
                arguments[0] = newValue;
            } else {
                newValue = DefaultTypeTransformation.castToType(
                        newValue,
                        method.getParameterTypes()[1].getTheClass());
                arguments[1] = newValue;
            }

            VM_PLUGIN.transformMetaMethod(this, method).doMethodInvoke(object, arguments);
            return;
        }

        //----------------------------------------------------------------------
        // missing property protocol
        //----------------------------------------------------------------------
        if (ambiguousListener) {
            throw new GroovyRuntimeException("There are multiple listeners for the property " + name + ". Please do not use the bean short form to access this listener.");
        }
        if (mp != null) {
            throw new ReadOnlyPropertyException(name, theClass);
        }
        if (object instanceof Class && !"metaClass".equals(name)) {
            invokeStaticMissingProperty(object, name, newValue, false);
        } else {
            invokeMissingProperty(object, name, newValue, false);
        }
    }