public static Method getWriteMethod(Class target, String name, Class[] argClasses)
    {
        try {
            if (name.indexOf('"') >= 0)
                name = name.replaceAll("\"", "");

            BeanInfo info = Introspector.getBeanInfo(target);
            MethodDescriptor[] methods = info.getMethodDescriptors();

            ArrayList<Method> candidates = new ArrayList<Method>();

            for (int i = 0; i < methods.length; i++) {
                if (!isMethodCallable(methods[i].getMethod()))
                    continue;

                if ((methods[i].getName().equalsIgnoreCase(name)
                     || methods[i].getName().toLowerCase().equals(name.toLowerCase())
                     || methods[i].getName().toLowerCase().equals("set" + name.toLowerCase()))
                    && !methods[i].getName().startsWith("get")) {

                    candidates.add(methods[i].getMethod());
                }
            }

            if (!candidates.isEmpty()) {
                MatchingMethod mm = findBestMethod(candidates, target, name, argClasses);
                if (mm != null)
                    return mm.mMethod;
            }
            // try again on pure class

            Method[] cmethods = target.getClass().getMethods();
            for (int i = 0; i < cmethods.length; i++) {
                if (!isMethodCallable(cmethods[i]))
                    continue;

                if ((cmethods[i].getName().equalsIgnoreCase(name)
                     || cmethods[i].getName().toLowerCase().equals(name.toLowerCase())
                     || cmethods[i].getName().toLowerCase().equals("set" + name.toLowerCase()))
                    && !cmethods[i].getName().startsWith("get")) {

                    Method m = methods[i].getMethod();
                    if (!candidates.contains(m))
                        candidates.add(m);
                }
            }

            if (!candidates.isEmpty()) {
                MatchingMethod mm = findBestMethod(candidates, target, name, argClasses);
                if (mm != null)
                    return mm.mMethod;
            }
            // try one last time adding a set to beginning

            if (!name.startsWith("set")) {
                Method ret = OgnlRuntime.getReadMethod(target, "set" + name, argClasses);
                if (ret != null)
                    return ret;
            }

            if (!candidates.isEmpty()) {
                // we need to do conversions.
                // TODO we have to find out which conversions are possible!
                int reqArgCount = argClasses==null?0:argClasses.length;
                for (Method m : candidates) {
                    if (m.getParameterTypes().length == reqArgCount)
                        return m;
                }

                if ( argClasses == null && candidates.size() == 1 ) {
                    // this seems to be the TestCase TestOgnlRuntime.test_Complicated_Inheritance() - is this a real world use case?
                    return candidates.get(0);
                }
            }
        } catch (Throwable t)
        {
            throw OgnlOps.castToRuntime(t);
        }

        return null;
    }