Example usage for java.lang.reflect Method getAnnotations

List of usage examples for java.lang.reflect Method getAnnotations

Introduction

In this page you can find the example usage for java.lang.reflect Method getAnnotations.

Prototype

public Annotation[] getAnnotations() 

Source Link

Usage

From source file:org.castor.jaxb.reflection.ClassInfoBuilder.java

/**
 * Build the FieldInfo for a Method.//from  w  w w .  j  a v a  2  s.c om
 * 
 * @param classInfo
 *            the ClassInfo to look in if this field already exists
 * @param method
 *            the Method to describe
 * @return the ClassInfo containing the FieldInfo build
 */
private void buildFieldInfo(final ClassInfo classInfo, final Method method) {
    if (classInfo == null) {
        String message = "Argument classInfo must not be null.";
        LOG.warn(message);
        throw new IllegalArgumentException(message);
    }
    if (method == null) {
        String message = "Argument method must not be null.";
        LOG.warn(message);
        throw new IllegalArgumentException(message);
    }
    String fieldName = javaNaming.extractFieldNameFromMethod(method);
    FieldInfo fieldInfo = classInfo.getFieldInfo(fieldName);
    if (fieldInfo == null) {
        fieldInfo = createFieldInfo(fieldName);
        classInfo.addFieldInfo(fieldInfo);
        fieldInfo.setParentClassInfo(classInfo);
    }
    JaxbFieldNature jaxbFieldNature = new JaxbFieldNature(fieldInfo);
    if (javaNaming.isAddMethod(method)) {
        jaxbFieldNature.setMethodAdd(method);
        jaxbFieldNature.setMultivalued(true);
    } else if (javaNaming.isCreateMethod(method)) {
        jaxbFieldNature.setMethodCreate(method);
    } else if (javaNaming.isGetMethod(method)) {
        jaxbFieldNature.setMethodGet(method);
        handleMultivaluedness(method.getReturnType(), jaxbFieldNature, method.getGenericReturnType());
    } else if (javaNaming.isSetMethod(method)) {
        jaxbFieldNature.setMethodSet(method);
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes.length == 1) {
            handleMultivaluedness(parameterTypes[0], jaxbFieldNature, method.getGenericParameterTypes()[0]);
        }
    } else if (javaNaming.isIsMethod(method)) {
        jaxbFieldNature.setMethodIs(method);
    } else {
        if (LOG.isDebugEnabled()) {
            String message = "Method: " + method + " is of unsupported type and ignored.";
            LOG.debug(message);
        }
    }
    fieldAnnotationProcessingService.processAnnotations(jaxbFieldNature, method.getAnnotations());
}

From source file:org.LexGrid.LexBIG.caCore.client.proxy.LexEVSApplicationServiceProxy.java

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
    //This is for Spring -- if it tries to call methods (like set the LexEVSApplicationService,
    //'toString', etc, on the creation of the bean. If we haven't set up the LexEVSApplicationService,
    //we can't do any of the remoting anyway.
    if (eas == null) {
        return invocation.proceed();
    }//ww w . ja va2  s.c  om

    Object bean = invocation.getThis();
    Method method = invocation.getMethod();
    String methodName = method.getName();

    Object[] args = invocation.getArguments();
    Class implClass = bean.getClass();

    SecurityToken securityToken = null;
    String vocabulary = null;

    if (methodName.equals("getSecurityToken_map")) {
        return securityToken_map;
    }

    // Check if the invocation.methodName is registerToken
    if (methodName.equals("registerSecurityToken")) {

        /* User needs to determine which vocabulary to register
         * User needs to pass vocabulary name and token string.
         * registerSecurityToken(String vocabulary, String token)
         * First argument is assumed to be vocabulary name
         */
        vocabulary = (String) args[0];

        // Second parameter of registerSecurityToken method is assumed to be SecurityToken
        securityToken = (SecurityToken) args[1];

        if ((vocabulary.equals(null)) || (vocabulary == "")) {
            throw new IllegalArgumentException("vocabulary is null..args");
        }

        if (securityToken == null) {
            throw new IllegalArgumentException("Security token arg is null... ");
        }

        // insert them in the securityToken_map hashmap if not already present
        securityToken_map.put(vocabulary, securityToken);

        // return Boolean.TRUE or Boolean.FALSE
        return true;
    }

    /* Check if the method is annotated as requiring security token
     * (e.g., resolveCodingScheme() and handle it aptly
     * whether the coding scheme itself requires a security token (determined by configuration file)
      */
    if (methodName.equals("executeSecurely")) {
        if (isDataServiceLazyLoadable(args)) {
            return invokeDataService(invocation);
        }
        return super.invoke(invocation);
    } else {

        Method methodImpl = implClass.getMethod(methodName, method.getParameterTypes());

        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                if (args[i] != null) {
                    if (Enhancer.isEnhanced(args[i].getClass())) {
                        args[i] = unwrap(args[i]);
                    }
                }
            }
        }
        try {
            return eas.executeSecurely(methodImpl.getName(), method.getAnnotations(),
                    getParameterTypes(methodImpl), args, securityToken_map);
        } catch (Exception e) {
            // throw e;
            throw digOutRealExceptionAndThrowIt(e);
            // throw new LBException("Something went wrong.");
            // digOutRealExceptionAndThrowIt();
        }
    }
}

From source file:com.meidusa.venus.client.RemotingInvocationHandler.java

protected Object invokeRemoteService(Service service, Endpoint endpoint, Method method,
        EndpointParameter[] params, Object[] args) throws Exception {
    String apiName = VenusAnnotationUtils.getApiname(method, service, endpoint);

    AthenaTransactionId athenaTransactionId = null;
    if (service.athenaFlag()) {
        athenaTransactionId = AthenaTransactionDelegate.getDelegate().startClientTransaction(apiName);
    }/*from   ww  w .ja  v  a2  s.c o m*/
    boolean async = false;

    if (endpoint.async()) {
        async = true;
    }

    byte[] traceID = VenusTracerUtil.getTracerID();

    if (traceID == null) {
        traceID = VenusTracerUtil.randomTracerID();
    }

    Serializer serializer = SerializerFactory.getSerializer(serializeType);

    SerializeServiceRequestPacket serviceRequestPacket = new SerializeServiceRequestPacket(serializer, null);

    serviceRequestPacket.clientId = PacketConstant.VENUS_CLIENT_ID;
    serviceRequestPacket.clientRequestId = sequenceId.getAndIncrement();
    serviceRequestPacket.traceId = traceID;
    serviceRequestPacket.apiName = apiName;
    serviceRequestPacket.serviceVersion = service.version();
    serviceRequestPacket.parameterMap = new HashMap<String, Object>();

    if (params != null) {
        for (int i = 0; i < params.length; i++) {
            if (args[i] instanceof InvocationListener) {
                async = true;
                ReferenceInvocationListener listener = new ReferenceInvocationListener();
                ServicePacketBuffer buffer = new ServicePacketBuffer(16);
                buffer.writeLengthCodedString(args[i].getClass().getName(), "utf-8");
                buffer.writeInt(System.identityHashCode(args[i]));
                listener.setIdentityData(buffer.toByteBuffer().array());
                Type type = method.getGenericParameterTypes()[i];
                if (type instanceof ParameterizedType) {
                    ParameterizedType genericType = ((ParameterizedType) type);
                    container.putInvocationListener((InvocationListener) args[i],
                            genericType.getActualTypeArguments()[0]);
                } else {
                    throw new InvalidParameterException("invocationListener is not generic");
                }

                serviceRequestPacket.parameterMap.put(params[i].getParamName(), listener);
            } else {
                serviceRequestPacket.parameterMap.put(params[i].getParamName(), args[i]);
            }

        }
    }
    setTransactionId(serviceRequestPacket, athenaTransactionId);

    PerformanceLevel pLevel = AnnotationUtil.getAnnotation(method.getAnnotations(), PerformanceLevel.class);
    long start = TimeUtil.currentTimeMillis();
    long borrowed = start;

    if (async) {
        if (!this.isEnableAsync()) {
            throw new VenusConfigException("service async call disabled");
        }

        BackendConnection conn = null;
        try {

            if (nioConnPool instanceof RequestLoadbalanceObjectPool) {
                conn = (BackendConnection) ((RequestLoadbalanceObjectPool) nioConnPool)
                        .borrowObject(serviceRequestPacket.parameterMap, endpoint);
            } else {
                conn = nioConnPool.borrowObject();
            }
            borrowed = TimeUtil.currentTimeMillis();

            conn.write(serviceRequestPacket.toByteBuffer());
            VenusTracerUtil.logRequest(traceID, serviceRequestPacket.apiName,
                    JSON.toJSONString(serviceRequestPacket.parameterMap, JSON_FEATURE));
            return null;
        } finally {
            if (service.athenaFlag()) {
                AthenaTransactionDelegate.getDelegate().completeClientTransaction();
            }
            if (performanceLogger.isDebugEnabled()) {
                long end = TimeUtil.currentTimeMillis();
                long time = end - borrowed;
                StringBuffer buffer = new StringBuffer();
                buffer.append("[").append(borrowed - start).append(",").append(time)
                        .append("]ms (*client,async*) traceID=").append(UUID.toString(traceID)).append(", api=")
                        .append(serviceRequestPacket.apiName);

                performanceLogger.debug(buffer.toString());
            }

            if (conn != null) {
                nioConnPool.returnObject(conn);
            }
        }
    } else {
        AbstractBIOConnection conn = null;
        int soTimeout = 0;
        int oldTimeout = 0;
        boolean success = true;
        int errorCode = 0;
        AbstractServicePacket packet = null;
        String remoteAddress = null;
        boolean invalided = false;
        try {
            if (bioConnPool instanceof RequestLoadbalanceObjectPool) {
                conn = (AbstractBIOConnection) ((RequestLoadbalanceObjectPool) bioConnPool)
                        .borrowObject(serviceRequestPacket.parameterMap, endpoint);
            } else {
                conn = (AbstractBIOConnection) bioConnPool.borrowObject();
            }
            remoteAddress = conn.getRemoteAddress();
            borrowed = TimeUtil.currentTimeMillis();
            ServiceConfig config = this.serviceFactory.getServiceConfig(method.getDeclaringClass());

            oldTimeout = conn.getSoTimeout();
            if (config != null) {
                EndpointConfig endpointConfig = config.getEndpointConfig(endpoint.name());
                if (endpointConfig != null) {
                    int eTimeOut = endpointConfig.getTimeWait();
                    if (eTimeOut > 0) {
                        soTimeout = eTimeOut;
                    }
                } else {
                    if (config.getTimeWait() > 0) {
                        soTimeout = config.getTimeWait();
                    } else {
                        if (endpoint.timeWait() > 0) {
                            soTimeout = endpoint.timeWait();
                        }
                    }
                }

            } else {

                if (endpoint.timeWait() > 0) {
                    soTimeout = endpoint.timeWait();
                }
            }

            byte[] bts;

            try {

                if (soTimeout > 0) {
                    conn.setSoTimeout(soTimeout);
                }
                conn.write(serviceRequestPacket.toByteArray());
                VenusTracerUtil.logRequest(traceID, serviceRequestPacket.apiName,
                        JSON.toJSONString(serviceRequestPacket.parameterMap, JSON_FEATURE));
                bts = conn.read();
            } catch (IOException e) {
                try {
                    conn.close();
                } catch (Exception e1) {
                    // ignore
                }

                bioConnPool.invalidateObject(conn);
                invalided = true;
                Class<?>[] eClass = method.getExceptionTypes();

                if (eClass != null && eClass.length > 0) {
                    for (Class<?> clazz : eClass) {
                        if (e.getClass().isAssignableFrom(clazz)) {
                            throw e;
                        }
                    }
                }

                throw new RemoteSocketIOException("api=" + serviceRequestPacket.apiName + ", remoteIp="
                        + conn.getRemoteAddress() + ",(" + e.getMessage() + ")", e);
            }

            int type = AbstractServicePacket.getType(bts);
            switch (type) {
            case PacketConstant.PACKET_TYPE_ERROR:
                ErrorPacket error = new ErrorPacket();
                error.init(bts);
                packet = error;
                Exception e = venusExceptionFactory.getException(error.errorCode, error.message);
                if (e == null) {
                    throw new DefaultVenusException(error.errorCode, error.message);
                } else {
                    if (error.additionalData != null) {
                        Map<String, Type> tmap = Utils.getBeanFieldType(e.getClass(), Exception.class);
                        if (tmap != null && tmap.size() > 0) {
                            Object obj = serializer.decode(error.additionalData, tmap);
                            BeanUtils.copyProperties(e, obj);
                        }
                    }
                    throw e;
                }
            case PacketConstant.PACKET_TYPE_OK:
                OKPacket ok = new OKPacket();
                ok.init(bts);
                packet = ok;
                return null;
            case PacketConstant.PACKET_TYPE_SERVICE_RESPONSE:
                ServiceResponsePacket response = new SerializeServiceResponsePacket(serializer,
                        method.getGenericReturnType());
                response.init(bts);
                packet = response;
                return response.result;
            default: {
                logger.warn("unknow response type=" + type);
                success = false;
                return null;
            }
            }
        } catch (Exception e) {
            success = false;

            if (e instanceof CodedException
                    || (errorCode = venusExceptionFactory.getErrorCode(e.getClass())) != 0
                    || e instanceof RuntimeException) {
                if (e instanceof CodedException) {
                    errorCode = ((CodedException) e).getErrorCode();
                }
                throw e;
            } else {
                RemoteException code = e.getClass().getAnnotation(RemoteException.class);
                if (code != null) {
                    errorCode = code.errorCode();
                    throw e;
                } else {
                    ExceptionCode eCode = e.getClass().getAnnotation(ExceptionCode.class);
                    if (eCode != null) {
                        errorCode = eCode.errorCode();
                        throw e;
                    } else {
                        errorCode = -1;
                        if (conn == null) {
                            throw new DefaultVenusException(e.getMessage(), e);
                        } else {
                            throw new DefaultVenusException(
                                    e.getMessage() + ". remoteAddress=" + conn.getRemoteAddress(), e);
                        }
                    }
                }
            }
        } finally {
            if (service.athenaFlag()) {
                AthenaTransactionDelegate.getDelegate().completeClientTransaction();
            }
            long end = TimeUtil.currentTimeMillis();
            long time = end - borrowed;
            StringBuffer buffer = new StringBuffer();
            buffer.append("[").append(borrowed - start).append(",").append(time)
                    .append("]ms (*client,sync*) traceID=").append(UUID.toString(traceID)).append(", api=")
                    .append(serviceRequestPacket.apiName);
            if (remoteAddress != null) {
                buffer.append(", remote=").append(remoteAddress);
            } else {
                buffer.append(", pool=").append(bioConnPool.toString());
            }
            buffer.append(", clientID=").append(PacketConstant.VENUS_CLIENT_ID).append(", requestID=")
                    .append(serviceRequestPacket.clientRequestId);

            if (packet != null) {
                if (packet instanceof ErrorPacket) {
                    buffer.append(", errorCode=").append(((ErrorPacket) packet).errorCode);
                    buffer.append(", message=").append(((ErrorPacket) packet).message);
                } else {
                    buffer.append(", errorCode=0");
                }
            }

            if (pLevel != null) {

                if (pLevel.printParams()) {
                    buffer.append(", params=");
                    buffer.append(JSON.toJSONString(serviceRequestPacket.parameterMap, JSON_FEATURE));
                }

                if (time > pLevel.error() && pLevel.error() > 0) {
                    if (performanceLogger.isErrorEnabled()) {
                        performanceLogger.error(buffer.toString());
                    }
                } else if (time > pLevel.warn() && pLevel.warn() > 0) {
                    if (performanceLogger.isWarnEnabled()) {
                        performanceLogger.warn(buffer.toString());
                    }
                } else if (time > pLevel.info() && pLevel.info() > 0) {
                    if (performanceLogger.isInfoEnabled()) {
                        performanceLogger.info(buffer.toString());
                    }
                } else {
                    if (performanceLogger.isDebugEnabled()) {
                        performanceLogger.debug(buffer.toString());
                    }
                }
            } else {
                buffer.append(", params=");
                buffer.append(JSON.toJSONString(serviceRequestPacket.parameterMap, JSON_FEATURE));

                if (time >= 30 * 1000) {
                    if (performanceLogger.isErrorEnabled()) {
                        performanceLogger.error(buffer.toString());
                    }
                } else if (time >= 10 * 1000) {
                    if (performanceLogger.isWarnEnabled()) {
                        performanceLogger.warn(buffer.toString());
                    }
                } else if (time >= 5 * 1000) {
                    if (performanceLogger.isInfoEnabled()) {
                        performanceLogger.info(buffer.toString());
                    }
                } else {
                    if (performanceLogger.isDebugEnabled()) {
                        performanceLogger.debug(buffer.toString());
                    }
                }
            }

            if (conn != null && !invalided) {
                if (!conn.isClosed() && soTimeout > 0) {
                    conn.setSoTimeout(oldTimeout);
                }
                bioConnPool.returnObject(conn);
            }

        }
    }
}

From source file:ca.oson.json.Oson.java

private <E, R> String object2Serialize(FieldData objectDTO) {
    E obj = (E) objectDTO.valueToProcess;

    Class<R> valueType = objectDTO.returnType;

    if (obj == null) {
        return null;
    }/*from   ww  w.  j  av a 2 s. co m*/

    // it is possible the same object shared by multiple variables inside the same enclosing object
    int hash = ObjectUtil.hashCode(obj, valueType);
    if (!objectDTO.goAhead(hash)) {
        return "{}";
    }

    ClassMapper classMapper = objectDTO.classMapper;
    // first build up the class-level processing rules
    // || (objectDTO.level == 0 && objectDTO.fieldMapper == null)
    //if (classMapper == null) {
    // 1. Create a blank class mapper instance
    classMapper = new ClassMapper(valueType);

    // 2. Globalize it
    classMapper = globalize(classMapper);
    objectDTO.classMapper = classMapper;
    //}

    if (objectDTO.fieldMapper != null && isInheritMapping()) {
        classMapper = overwriteBy(classMapper, objectDTO.fieldMapper);
    }

    FIELD_NAMING format = getFieldNaming();

    String repeated = getPrettyIndentationln(objectDTO.level), pretty = getPrettySpace();
    objectDTO.incrLevel();
    String repeatedItem = getPrettyIndentationln(objectDTO.level);

    // @Expose
    Set<String> exposed = null;
    if (isUseGsonExpose()) {
        exposed = new HashSet<>();
    }

    boolean annotationSupport = getAnnotationSupport();
    Annotation[] annotations = null;

    if (annotationSupport) {
        annotations = valueType.getAnnotations();

        ca.oson.json.annotation.ClassMapper classMapperAnnotation = null;

        // 3. Apply annotations from other sources
        for (Annotation annotation : annotations) {
            if (ignoreClass(annotation)) {
                return null;
            }

            switch (annotation.annotationType().getName()) {
            case "ca.oson.json.annotation.ClassMapper":
                classMapperAnnotation = (ca.oson.json.annotation.ClassMapper) annotation;
                if (!(classMapperAnnotation.serialize() == BOOLEAN.BOTH
                        || classMapperAnnotation.serialize() == BOOLEAN.TRUE)) {
                    classMapperAnnotation = null;
                }
                break;

            case "ca.oson.json.annotation.ClassMappers":
                ca.oson.json.annotation.ClassMappers classMapperAnnotations = (ca.oson.json.annotation.ClassMappers) annotation;
                for (ca.oson.json.annotation.ClassMapper ann : classMapperAnnotations.value()) {
                    if (ann.serialize() == BOOLEAN.BOTH || ann.serialize() == BOOLEAN.TRUE) {
                        classMapperAnnotation = ann;
                        //break;
                    }
                }
                break;

            case "com.google.gson.annotations.Since":
                Since since = (Since) annotation;
                classMapper.since = since.value();
                break;

            case "com.google.gson.annotations.Until":
                Until until = (Until) annotation;
                classMapper.until = until.value();
                break;

            case "com.fasterxml.jackson.annotation.JsonIgnoreProperties":
                JsonIgnoreProperties jsonIgnoreProperties = (JsonIgnoreProperties) annotation;
                String[] jsonnames = jsonIgnoreProperties.value();
                if (jsonnames != null && jsonnames.length > 0) {
                    if (classMapper.jsonIgnoreProperties == null) {
                        classMapper.jsonIgnoreProperties = new HashSet();
                    }

                    classMapper.jsonIgnoreProperties.addAll(Arrays.asList(jsonnames));
                }
                break;

            case "org.codehaus.jackson.annotate.JsonIgnoreProperties":
                org.codehaus.jackson.annotate.JsonIgnoreProperties jsonIgnoreProperties2 = (org.codehaus.jackson.annotate.JsonIgnoreProperties) annotation;
                String[] jsonnames2 = jsonIgnoreProperties2.value();
                if (jsonnames2 != null && jsonnames2.length > 0) {
                    if (classMapper.jsonIgnoreProperties == null) {
                        classMapper.jsonIgnoreProperties = new HashSet();
                    }

                    classMapper.jsonIgnoreProperties.addAll(Arrays.asList(jsonnames2));
                }
                break;

            case "com.fasterxml.jackson.annotation.JsonPropertyOrder":
                // first come first serve
                if (classMapper.propertyOrders == null) {
                    classMapper.propertyOrders = ((JsonPropertyOrder) annotation).value();
                }
                break;

            case "org.codehaus.jackson.annotate.JsonPropertyOrder":
                // first come first serve
                if (classMapper.propertyOrders == null) {
                    classMapper.propertyOrders = ((org.codehaus.jackson.annotate.JsonPropertyOrder) annotation)
                            .value();
                }
                break;

            case "com.fasterxml.jackson.annotation.JsonInclude":
                if (classMapper.defaultType == JSON_INCLUDE.NONE) {
                    JsonInclude jsonInclude = (JsonInclude) annotation;
                    switch (jsonInclude.content()) {
                    case ALWAYS:
                        classMapper.defaultType = JSON_INCLUDE.ALWAYS;
                        break;
                    case NON_NULL:
                        classMapper.defaultType = JSON_INCLUDE.NON_NULL;
                        break;
                    case NON_ABSENT:
                        classMapper.defaultType = JSON_INCLUDE.NON_NULL;
                        break;
                    case NON_EMPTY:
                        classMapper.defaultType = JSON_INCLUDE.NON_EMPTY;
                        break;
                    case NON_DEFAULT:
                        classMapper.defaultType = JSON_INCLUDE.NON_DEFAULT;
                        break;
                    case USE_DEFAULTS:
                        classMapper.defaultType = JSON_INCLUDE.DEFAULT;
                        break;
                    }
                }
                break;

            case "com.fasterxml.jackson.annotation.JsonAutoDetect":
                JsonAutoDetect jsonAutoDetect = (JsonAutoDetect) annotation;
                if (jsonAutoDetect.fieldVisibility() == Visibility.NONE) {
                    classMapper.useField = false;
                }
                if (jsonAutoDetect.getterVisibility() == Visibility.NONE) {
                    classMapper.useAttribute = false;
                }
                break;

            case "org.codehaus.jackson.annotate.JsonAutoDetect":
                org.codehaus.jackson.annotate.JsonAutoDetect jsonAutoDetect2 = (org.codehaus.jackson.annotate.JsonAutoDetect) annotation;
                if (jsonAutoDetect2
                        .fieldVisibility() == org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE) {
                    classMapper.useField = false;
                }
                if (jsonAutoDetect2
                        .getterVisibility() == org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE) {
                    classMapper.useAttribute = false;
                }

                break;

            case "org.junit.Ignore":
                classMapper.ignore = true;
                break;
            }
        }

        // 4. Apply annotations from Oson
        if (classMapperAnnotation != null) {
            classMapper = overwriteBy(classMapper, classMapperAnnotation);
            exposed = null;
        }

    }

    // 5. Apply Java configuration for this particular class
    ClassMapper javaClassMapper = getClassMapper(valueType);
    if (javaClassMapper != null) {
        classMapper = overwriteBy(classMapper, javaClassMapper);
    }

    // now processing at the class level

    if (classMapper.ignore()) {
        return null;
    }

    if (classMapper.since != null && classMapper.since > getVersion()) {
        return null;
    } else if (classMapper.until != null && classMapper.until <= getVersion()) {
        return null;
    }

    Function function = classMapper.serializer; //getSerializer(valueType);
    if (function == null) {
        function = DeSerializerUtil.getSerializer(valueType.getName());
    }

    if (function != null) {
        try {
            Object returnValue = null;
            if (function instanceof DataMapper2JsonFunction) {
                DataMapper classData = new DataMapper(valueType, obj, classMapper, objectDTO.level,
                        getPrettyIndentation());
                objectDTO.jsonRawValue = false;
                DataMapper2JsonFunction f = (DataMapper2JsonFunction) function;

                return f.apply(classData);

            } else if (function instanceof FieldData2JsonFunction) {
                FieldData2JsonFunction f = (FieldData2JsonFunction) function;
                FieldData fieldData = objectDTO.clone();

                returnValue = f.apply(fieldData);

            } else {
                returnValue = function.apply(obj);
            }

            if (returnValue != null) {
                Class returnType = returnValue.getClass();

                if (returnType == String.class) {
                    return StringUtil.doublequote(returnValue, isEscapeHtml());

                } else if (returnType == valueType || valueType.isAssignableFrom(returnType)) {
                    // just continue to do the serializing
                } else {
                    objectDTO.valueToProcess = returnValue;
                    objectDTO.returnType = returnType;

                    return object2String(objectDTO);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    Set<Class> ignoreFieldsWithAnnotations = classMapper.ignoreFieldsWithAnnotations;

    Map<String, String> keyJsonStrings = new LinkedHashMap<>();
    // to hold relation between name and changed name
    Map<String, String> fieldNames = new LinkedHashMap<>();

    Set<String> processedNameSet = new HashSet<>();
    //StringBuffer sb = new StringBuffer();

    Map<String, Method> getters = null;
    Map<String, Method> setters = null;
    Map<String, Method> otherMethods = null;

    if (valueType.isInterface()) {
        valueType = (Class<R>) obj.getClass();
    } else if (Modifier.isAbstract(valueType.getModifiers())) {
        // valueType

    } else {
        //         Class objClass = obj.getClass();
        //         if (valueType.isAssignableFrom(objClass)) {
        //            valueType = objClass;
        //         }
    }

    //      if (valueType.isInterface()) {
    //         getters = getGetters(obj);
    //         setters = getSetters(obj);
    //         otherMethods = getOtherMethods(obj);
    //      } else {
    getters = getGetters(valueType);
    setters = getSetters(valueType);
    otherMethods = getOtherMethods(valueType);
    //      }

    Set<Method> jsonAnyGetterMethods = new HashSet<>();

    if (classMapper.isToStringAsSerializer()) {
        try {
            Method getter = valueType.getDeclaredMethod("toString", null);

            if (getter != null) {
                E getterValue = ObjectUtil.getMethodValue(obj, getter);

                if (getterValue != null) {
                    Class returnType = getterValue.getClass();

                    if (returnType == String.class) {
                        return StringUtil.doublequote(getterValue, isEscapeHtml());

                    } else if (returnType == valueType || valueType.isAssignableFrom(returnType)) {
                        // just continue to do the serializing
                    } else {
                        objectDTO.valueToProcess = getterValue;
                        objectDTO.returnType = returnType;

                        return object2String(objectDTO);
                    }
                }
            }

        } catch (NoSuchMethodException | SecurityException e) {
            // e.printStackTrace();
        }
    }

    //if (getters != null && getters.size() > 0) {
    boolean isJsonRawValue = false;
    String jsonValueFieldName = DeSerializerUtil.getJsonValueFieldName(valueType.getName());
    //         if (jsonValueFieldName == null) {
    //            // get all fieldmappers for this class?
    //            Set<FieldMapper> fieldMappers = getFieldMappers(valueType);
    //            // looking for the method
    //            for (FieldMapper fieldMapper: fieldMappers) {
    //               if (fieldMapper.jsonValue != null && fieldMapper.jsonValue) {
    //                  jsonValueFieldName = fieldMapper.java;
    //                  isJsonRawValue = fieldMapper.isJsonRawValue();
    //                  break;
    //               }
    //            }
    //         }
    if (jsonValueFieldName == null) {
        jsonValueFieldName = classMapper.getJsonValueFieldName();
    }

    if (jsonValueFieldName != null) {
        String lcjava = jsonValueFieldName.toLowerCase();
        Method getter = null;
        if (getters != null && getters.containsKey(lcjava)) {
            getter = getters.get(lcjava);

        } else {
            try {
                getter = valueType.getMethod(jsonValueFieldName);
            } catch (NoSuchMethodException | SecurityException e) {
                // e.printStackTrace();
            }

            if (getter == null) {
                try {
                    getter = valueType.getMethod("get" + StringUtil.capitalize(jsonValueFieldName));
                } catch (NoSuchMethodException | SecurityException e) {
                    //e.printStackTrace();
                }
            }
        }

        if (getter != null) {
            E getterValue = ObjectUtil.getMethodValue(obj, getter);

            if (getterValue != null) {
                Class returnType = getterValue.getClass();

                if (returnType == String.class) {
                    if (isJsonRawValue) {
                        return getterValue.toString();

                    } else if (StringUtil.parenthesized(getterValue.toString())) {
                        return getterValue.toString();

                    } else {
                        return StringUtil.doublequote(getterValue, isEscapeHtml());
                    }

                } else if (returnType == valueType || valueType.isAssignableFrom(returnType)) {
                    // just continue to do the serializing
                } else {
                    objectDTO.valueToProcess = getterValue;
                    objectDTO.returnType = returnType;
                    objectDTO.jsonRawValue = isJsonRawValue;

                    return object2String(objectDTO);
                }
            }
        }
    }
    //}

    try {
        Field[] fields = null;
        //         if (valueType.isInterface()) {
        //            fields = getFields(obj);
        //         } else {
        fields = getFields(valueType);
        //         }

        for (Field f : fields) {
            f.setAccessible(true);

            String name = f.getName();
            String fieldName = name;
            String lcfieldName = fieldName.toLowerCase();

            if (Modifier.isFinal(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) {
                getters.remove(lcfieldName);
                continue;
            }

            // 6. Create a blank field mapper instance
            FieldMapper fieldMapper = new FieldMapper(name, name, valueType);

            Class<?> returnType = f.getType(); // value.getClass();

            // 7. get the class mapper of returnType
            ClassMapper fieldClassMapper = getClassMapper(returnType);

            // 8. Classify this field mapper with returnType
            fieldMapper = classifyFieldMapper(fieldMapper, fieldClassMapper);

            // 9. Classify this field mapper
            fieldMapper = classifyFieldMapper(fieldMapper, classMapper);

            FieldMapper javaFieldMapper = getFieldMapper(name, null, valueType);

            // getter and setter methods
            Method getter = getters.get(lcfieldName);
            Method setter = setters.get(lcfieldName);

            if (getter != null) {
                getter.setAccessible(true);
            }

            // control by visibility is not always a good idea
            // here consider the visibility of field and related getter method together
            if (ignoreModifiers(f.getModifiers(), classMapper.includeFieldsWithModifiers)) {
                if (getter != null) {
                    if (ignoreModifiers(getter.getModifiers(), classMapper.includeFieldsWithModifiers)) {
                        getters.remove(lcfieldName);
                        continue;
                    }
                } else {
                    continue;
                }
            }

            boolean ignored = false;
            Set<String> names = new HashSet<>();

            if (annotationSupport) {
                annotations = f.getDeclaredAnnotations();//.getAnnotations();

                // field and getter should be treated the same way, if allowed in the class level
                // might not be 100% correct, as the useAttribute as not be applied from annotations yet
                //  && ((javaFieldMapper == null || javaFieldMapper.useAttribute == null) && (fieldMapper.useAttribute == null || fieldMapper.useAttribute))
                // || (javaFieldMapper != null && javaFieldMapper.useAttribute != null && javaFieldMapper.useAttribute)
                // annotations might apply to method only, not the field, so need to get them, regardless using attribute or not
                if (getter != null) {
                    annotations = Stream
                            .concat(Arrays.stream(annotations), Arrays.stream(getter.getDeclaredAnnotations()))
                            .toArray(Annotation[]::new);

                    // no annotations, then try set method
                    if ((annotations == null || annotations.length == 0) && setter != null) {
                        annotations = setter.getDeclaredAnnotations();
                    }
                }

                ca.oson.json.annotation.FieldMapper fieldMapperAnnotation = null;

                for (Annotation annotation : annotations) {
                    if (ignoreField(annotation, ignoreFieldsWithAnnotations)) {
                        ignored = true;
                        break;

                    } else if (annotation instanceof ca.oson.json.annotation.FieldMapper) {
                        fieldMapperAnnotation = (ca.oson.json.annotation.FieldMapper) annotation;
                        if (!(fieldMapperAnnotation.serialize() == BOOLEAN.BOTH
                                || fieldMapperAnnotation.serialize() == BOOLEAN.TRUE)) {
                            fieldMapperAnnotation = null;
                        }

                    } else if (annotation instanceof ca.oson.json.annotation.FieldMappers) {
                        ca.oson.json.annotation.FieldMappers fieldMapperAnnotations = (ca.oson.json.annotation.FieldMappers) annotation;
                        for (ca.oson.json.annotation.FieldMapper ann : fieldMapperAnnotations.value()) {
                            if (ann.serialize() == BOOLEAN.BOTH || ann.serialize() == BOOLEAN.TRUE) {
                                fieldMapperAnnotation = ann;
                                //break;
                            }
                        }

                    } else {
                        // to improve performance, using swith on string
                        switch (annotation.annotationType().getName()) {

                        case "com.fasterxml.jackson.annotation.JsonAnyGetter":
                        case "org.codehaus.jackson.annotate.JsonAnyGetter":
                            fieldMapper.jsonAnyGetter = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonIgnore":
                        case "org.codehaus.jackson.annotate.JsonIgnore":
                            fieldMapper.ignore = true;
                            break;

                        case "javax.persistence.Transient":
                            ignored = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonIgnoreProperties":
                            JsonIgnoreProperties jsonIgnoreProperties = (JsonIgnoreProperties) annotation;
                            if (!jsonIgnoreProperties.allowGetters()) {
                                fieldMapper.ignore = true;
                            } else {
                                fieldMapper.ignore = false;
                                classMapper.jsonIgnoreProperties.remove(name);
                            }
                            break;

                        case "com.google.gson.annotations.Expose":
                            Expose expose = (Expose) annotation;
                            if (!expose.serialize()) {
                                fieldMapper.ignore = true;
                            } else if (exposed != null) {
                                exposed.add(lcfieldName);
                            }
                            break;

                        case "com.google.gson.annotations.Since":
                            Since since = (Since) annotation;
                            fieldMapper.since = since.value();
                            break;

                        case "com.google.gson.annotations.Until":
                            Until until = (Until) annotation;
                            fieldMapper.until = until.value();
                            break;

                        case "com.fasterxml.jackson.annotation.JsonInclude":
                            if (fieldMapper.defaultType == JSON_INCLUDE.NONE) {
                                JsonInclude jsonInclude = (JsonInclude) annotation;

                                switch (jsonInclude.content()) {
                                case ALWAYS:
                                    fieldMapper.defaultType = JSON_INCLUDE.ALWAYS;
                                    break;
                                case NON_NULL:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_NULL;
                                    break;
                                case NON_ABSENT:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_NULL;
                                    break;
                                case NON_EMPTY:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_EMPTY;
                                    break;
                                case NON_DEFAULT:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_DEFAULT;
                                    break;
                                case USE_DEFAULTS:
                                    fieldMapper.defaultType = JSON_INCLUDE.DEFAULT;
                                    break;
                                }
                            }
                            break;

                        case "com.fasterxml.jackson.annotation.JsonRawValue":
                            if (((JsonRawValue) annotation).value()) {
                                fieldMapper.jsonRawValue = true;
                            }
                            break;

                        case "org.codehaus.jackson.annotate.JsonRawValue":
                            if (((org.codehaus.jackson.annotate.JsonRawValue) annotation).value()) {
                                fieldMapper.jsonRawValue = true;
                            }
                            break;

                        case "com.fasterxml.jackson.annotation.JsonValue":
                        case "org.codehaus.jackson.annotate.JsonValue":
                            fieldMapper.jsonValue = true;
                            break;

                        case "org.junit.Ignore":
                            fieldMapper.ignore = true;
                            break;

                        case "javax.persistence.Enumerated":
                            fieldMapper.enumType = ((Enumerated) annotation).value();
                            break;

                        //                  case "javax.persistence.MapKeyEnumerated":
                        //                     mapper.enumType = ((javax.persistence.MapKeyEnumerated) annotation).value();
                        //                     break;

                        case "javax.validation.constraints.NotNull":
                            fieldMapper.required = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonProperty":
                            JsonProperty jsonProperty = (JsonProperty) annotation;
                            Access access = jsonProperty.access();
                            if (access == Access.WRITE_ONLY) {
                                fieldMapper.ignore = true;
                                break;
                            }

                            if (jsonProperty.required()) {
                                fieldMapper.required = true;
                            }

                            if (jsonProperty.defaultValue() != null
                                    && jsonProperty.defaultValue().length() > 0) {
                                fieldMapper.defaultValue = jsonProperty.defaultValue();
                            }
                            break;

                        case "javax.validation.constraints.Size":
                            Size size = (Size) annotation;
                            if (size.min() > 0) {
                                fieldMapper.min = (long) size.min();
                            }
                            if (size.max() < Integer.MAX_VALUE) {
                                fieldMapper.max = (long) size.max();
                            }
                            break;

                        case "javax.persistence.Column":
                            Column column = (Column) annotation;
                            if (column.length() != 255) {
                                fieldMapper.length = column.length();
                            }
                            if (column.scale() > 0) {
                                fieldMapper.scale = column.scale();
                            }

                            if (column.precision() > 0) {
                                fieldMapper.precision = column.precision();
                            }

                            if (!column.nullable()) {
                                fieldMapper.required = true;
                            }

                            break;
                        }

                        String fname = ObjectUtil.getName(annotation);
                        if (!StringUtil.isEmpty(fname)) {
                            names.add(fname);
                        }
                    }
                }

                // 10. Apply annotations from Oson
                // special name to handle
                if (fieldMapperAnnotation != null) {
                    fieldMapper = overwriteBy(fieldMapper, fieldMapperAnnotation, classMapper);
                    exposed = null;
                }
            }

            if (ignored) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            // 11. Apply Java configuration for this particular field
            if (javaFieldMapper != null && javaFieldMapper.isSerializing()) {
                fieldMapper = overwriteBy(fieldMapper, javaFieldMapper);
            }

            if (fieldMapper.ignore != null && fieldMapper.ignore) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            // in the ignored list
            if (ObjectUtil.inSet(name, classMapper.jsonIgnoreProperties)) {
                getters.remove(lcfieldName);
                continue;
            }

            if (fieldMapper.jsonAnyGetter != null && fieldMapper.jsonAnyGetter && getter != null) {
                getters.remove(lcfieldName);
                jsonAnyGetterMethods.add(getter);
                continue;
            }

            if (fieldMapper.useField != null && !fieldMapper.useField) {
                // both should not be used, just like ignore
                if (fieldMapper.useAttribute != null && !fieldMapper.useAttribute) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            if (fieldMapper.since != null && fieldMapper.since > getVersion()) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            } else if (fieldMapper.until != null && fieldMapper.until <= getVersion()) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            //jsonIgnoreProperties

            // handling name now
            boolean jnameFixed = false;
            String json = fieldMapper.json;
            if (StringUtil.isEmpty(json)) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;

            } else if (!json.equals(name)) {
                name = json;
                jnameFixed = true;
            }

            if (!jnameFixed) {
                for (String jsoname : names) {
                    if (!name.equals(jsoname) && !StringUtil.isEmpty(jsoname)) {
                        name = jsoname;
                        jnameFixed = true;
                        break;
                    }
                }
            }

            // only if the name is still the same as the field name
            // format it based on the naming settings
            // otherwise, it is set on purpose
            if (fieldName.equals(name)) {
                name = StringUtil.formatName(name, format);
                jnameFixed = true;
            }

            fieldMapper.java = fieldName;
            fieldMapper.json = name;

            // field valuie
            E value = null;
            try {
                value = (E) f.get(obj);// ObjectUtil.unwraponce(f.get(obj));
            } catch (Exception e) {
            }

            if (value != null) {
                Class vtype = value.getClass();
                if (returnType.isAssignableFrom(vtype)) {
                    returnType = vtype;
                }
            }

            // value from getter
            E getterValue = null;

            if (getter != null) {
                if (fieldMapper.useAttribute == null || fieldMapper.useAttribute) {
                    getterValue = ObjectUtil.getMethodValue(obj, getter);
                    //getterValue = ObjectUtil.unwraponce(getterValue);
                }

                getters.remove(lcfieldName);
            }

            // determine which value to use
            if (getterValue != null) {
                if (getterValue.equals(value) || StringUtil.isEmpty(value)) {
                    value = getterValue;

                } else if (DefaultValue.isDefault(value, returnType)
                        && !DefaultValue.isDefault(getterValue, returnType)) {
                    value = getterValue;
                }
                //               else if (getterValue.toString().length() > value.toString().length()) {
                //                  value = getterValue;
                //               }
            }

            String str;

            FieldData fieldData = new FieldData(obj, f, value, returnType, false, fieldMapper, objectDTO.level,
                    objectDTO.set);

            str = object2Json(fieldData);

            if (fieldMapper.jsonValue != null && fieldMapper.jsonValue) {
                if (fieldMapper.isJsonRawValue()) {
                    return StringUtil.unquote(str, isEscapeHtml());
                } else {
                    return StringUtil.doublequote(str, isEscapeHtml());
                }
            }

            if (StringUtil.isNull(str)) {
                if (fieldMapper.defaultType == JSON_INCLUDE.NON_NULL
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                    continue;

                } else {
                    str = "null";
                }

            } else if (StringUtil.isEmpty(str)) {
                if (fieldMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                    continue;
                }

                str = "\"\"";

            } else if (fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT
                    && DefaultValue.isDefault(str, returnType)) {
                continue;
            }

            StringBuffer sb = new StringBuffer();
            sb.append(repeatedItem);
            if (fieldMapper.jsonNoName == null || !fieldMapper.jsonNoName) {
                sb.append("\"" + name + "\":" + pretty);
            }
            sb.append(str);
            sb.append(",");

            keyJsonStrings.put(lcfieldName, sb.toString());
            processedNameSet.add(name);
            fieldNames.put(lcfieldName, name.toLowerCase());
        }

        // now process get methods
        for (Entry<String, Method> entry : getters.entrySet()) {
            String lcfieldName = entry.getKey();
            Method getter = entry.getValue();

            if (ignoreModifiers(getter.getModifiers(), classMapper.includeFieldsWithModifiers)) {
                continue;
            }
            if (Modifier.isFinal(getter.getModifiers()) && Modifier.isStatic(getter.getModifiers())) {
                continue;
            }

            String name = getter.getName();
            if (name.substring(3).equalsIgnoreCase(lcfieldName)) {
                name = StringUtil.uncapitalize(name.substring(3));
            }

            // just use field name, even it might not be a field
            String fieldName = name;

            if (processedNameSet.contains(name) || fieldNames.containsKey(lcfieldName)) {
                continue;
            }

            getter.setAccessible(true);

            Method setter = setters.get(lcfieldName);

            // 6. Create a blank field mapper instance
            FieldMapper fieldMapper = new FieldMapper(name, name, valueType);

            Class<?> returnType = getter.getReturnType();

            // 7. get the class mapper of returnType
            ClassMapper fieldClassMapper = getClassMapper(returnType);

            // 8. Classify this field mapper with returnType
            fieldMapper = classifyFieldMapper(fieldMapper, fieldClassMapper);

            // 9. Classify this field mapper
            fieldMapper = classifyFieldMapper(fieldMapper, classMapper);

            FieldMapper javaFieldMapper = getFieldMapper(name, null, valueType);

            boolean ignored = false;
            Set<String> names = new HashSet<>();

            if (annotationSupport) {
                annotations = getter.getDeclaredAnnotations();//.getAnnotations();

                // no annotations, then try set method
                if ((annotations == null || annotations.length == 0) && setter != null) {
                    annotations = setter.getDeclaredAnnotations();
                }

                ca.oson.json.annotation.FieldMapper fieldMapperAnnotation = null;

                for (Annotation annotation : annotations) {
                    if (ignoreField(annotation, ignoreFieldsWithAnnotations)) {
                        ignored = true;
                        break;

                    } else if (annotation instanceof ca.oson.json.annotation.FieldMapper) {
                        fieldMapperAnnotation = (ca.oson.json.annotation.FieldMapper) annotation;
                        if (!(fieldMapperAnnotation.serialize() == BOOLEAN.BOTH
                                || fieldMapperAnnotation.serialize() == BOOLEAN.TRUE)) {
                            fieldMapperAnnotation = null;
                        }

                    } else if (annotation instanceof ca.oson.json.annotation.FieldMappers) {
                        ca.oson.json.annotation.FieldMappers fieldMapperAnnotations = (ca.oson.json.annotation.FieldMappers) annotation;
                        for (ca.oson.json.annotation.FieldMapper ann : fieldMapperAnnotations.value()) {
                            if (ann.serialize() == BOOLEAN.BOTH || ann.serialize() == BOOLEAN.TRUE) {
                                fieldMapperAnnotation = ann;
                                //break;
                            }
                        }

                    } else {
                        // to improve performance, using swith on string
                        switch (annotation.annotationType().getName()) {
                        case "com.fasterxml.jackson.annotation.JsonAnyGetter":
                        case "org.codehaus.jackson.annotate.JsonAnyGetter":
                            fieldMapper.jsonAnyGetter = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonIgnore":
                        case "org.codehaus.jackson.annotate.JsonIgnore":
                            fieldMapper.ignore = true;
                            break;

                        case "javax.persistence.Transient":
                            ignored = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonIgnoreProperties":
                            JsonIgnoreProperties jsonIgnoreProperties = (JsonIgnoreProperties) annotation;
                            if (!jsonIgnoreProperties.allowGetters()) {
                                fieldMapper.ignore = true;
                            } else {
                                fieldMapper.ignore = false;
                                classMapper.jsonIgnoreProperties.remove(name);
                            }
                            break;

                        case "com.google.gson.annotations.Expose":
                            Expose expose = (Expose) annotation;
                            if (!expose.serialize()) {
                                fieldMapper.ignore = true;
                            } else if (exposed != null) {
                                exposed.add(lcfieldName);
                            }
                            break;

                        case "com.google.gson.annotations.Since":
                            Since since = (Since) annotation;
                            fieldMapper.since = since.value();
                            break;

                        case "com.google.gson.annotations.Until":
                            Until until = (Until) annotation;
                            fieldMapper.until = until.value();
                            break;

                        case "com.fasterxml.jackson.annotation.JsonInclude":
                            if (fieldMapper.defaultType == JSON_INCLUDE.NONE) {
                                JsonInclude jsonInclude = (JsonInclude) annotation;

                                switch (jsonInclude.content()) {
                                case ALWAYS:
                                    fieldMapper.defaultType = JSON_INCLUDE.ALWAYS;
                                    break;
                                case NON_NULL:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_NULL;
                                    break;
                                case NON_ABSENT:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_NULL;
                                    break;
                                case NON_EMPTY:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_EMPTY;
                                    break;
                                case NON_DEFAULT:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_DEFAULT;
                                    break;
                                case USE_DEFAULTS:
                                    fieldMapper.defaultType = JSON_INCLUDE.DEFAULT;
                                    break;
                                }
                            }
                            break;

                        case "com.fasterxml.jackson.annotation.JsonRawValue":
                            if (((JsonRawValue) annotation).value()) {
                                fieldMapper.jsonRawValue = true;
                            }
                            break;

                        case "org.codehaus.jackson.annotate.JsonRawValue":
                            if (((org.codehaus.jackson.annotate.JsonRawValue) annotation).value()) {
                                fieldMapper.jsonRawValue = true;
                            }
                            break;

                        case "com.fasterxml.jackson.annotation.JsonValue":
                        case "org.codehaus.jackson.annotate.JsonValue":
                            fieldMapper.jsonValue = true;
                            break;

                        case "javax.persistence.Enumerated":
                            fieldMapper.enumType = ((Enumerated) annotation).value();
                            break;

                        //                  case "javax.persistence.MapKeyEnumerated":
                        //                     mapper.enumType = ((javax.persistence.MapKeyEnumerated) annotation).value();
                        //                     break;

                        case "javax.validation.constraints.NotNull":
                            fieldMapper.required = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonProperty":
                            JsonProperty jsonProperty = (JsonProperty) annotation;
                            Access access = jsonProperty.access();
                            if (access == Access.WRITE_ONLY) {
                                fieldMapper.ignore = true;
                                break;
                            }

                            if (jsonProperty.required()) {
                                fieldMapper.required = true;
                            }

                            if (jsonProperty.defaultValue() != null
                                    && jsonProperty.defaultValue().length() > 0) {
                                fieldMapper.defaultValue = jsonProperty.defaultValue();
                            }
                            break;

                        case "org.junit.Ignore":
                            fieldMapper.ignore = true;
                            break;

                        case "javax.validation.constraints.Size":
                            Size size = (Size) annotation;
                            if (size.min() > 0) {
                                fieldMapper.min = (long) size.min();
                            }
                            if (size.max() < Integer.MAX_VALUE) {
                                fieldMapper.max = (long) size.max();
                            }
                            break;

                        case "javax.persistence.Column":
                            Column column = (Column) annotation;
                            if (column.length() != 255) {
                                fieldMapper.length = column.length();
                            }
                            if (column.scale() > 0) {
                                fieldMapper.scale = column.scale();
                            }

                            if (column.precision() > 0) {
                                fieldMapper.precision = column.precision();
                            }

                            if (!column.nullable()) {
                                fieldMapper.required = true;
                            }

                            break;
                        }

                        String fname = ObjectUtil.getName(annotation);
                        if (fname != null) {
                            names.add(fname);
                        }
                    }
                }

                // 10. Apply annotations from Oson
                // special name to handle
                if (fieldMapperAnnotation != null) {
                    fieldMapper = overwriteBy(fieldMapper, fieldMapperAnnotation, classMapper);
                    exposed = null;
                }
            }

            if (ignored) {
                continue;
            }

            // 11. Apply Java configuration for this particular field
            if (javaFieldMapper != null && javaFieldMapper.isSerializing()) {
                fieldMapper = overwriteBy(fieldMapper, javaFieldMapper);
            }

            if (fieldMapper.ignore != null && fieldMapper.ignore) {
                continue;
            }

            // in the ignored list
            if (ObjectUtil.inSet(name, classMapper.jsonIgnoreProperties)) {
                continue;
            }

            if (fieldMapper.jsonAnyGetter != null && fieldMapper.jsonAnyGetter) {
                jsonAnyGetterMethods.add(getter);
                continue;
            }

            if (fieldMapper.useAttribute != null && !fieldMapper.useAttribute) {
                continue;
            }

            if (fieldMapper.since != null && fieldMapper.since > getVersion()) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            } else if (fieldMapper.until != null && fieldMapper.until <= getVersion()) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            // handling name now
            boolean jnameFixed = false;
            String json = fieldMapper.json;
            if (StringUtil.isEmpty(json)) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;

            } else if (!json.equals(name)) {
                name = json;
                jnameFixed = true;
            }

            if (!jnameFixed) {
                for (String jsoname : names) {
                    if (!name.equals(jsoname) && !StringUtil.isEmpty(jsoname)) {
                        name = jsoname;
                        jnameFixed = true;
                        break;
                    }
                }
            }

            // only if the name is still the same as the field name
            // format it based on the naming settings
            // otherwise, it is set on purpose
            if (fieldName.equals(name)) {
                name = StringUtil.formatName(name, format);
                jnameFixed = true;
            }

            fieldMapper.java = fieldName;
            fieldMapper.json = name;

            // get value
            E value = ObjectUtil.getMethodValue(obj, getter);

            if (fieldMapper.jsonValue != null && fieldMapper.jsonValue) {
                if (value != null) {
                    if (fieldMapper.isJsonRawValue()) {
                        return value.toString();
                    } else {
                        return StringUtil.doublequote(value, isEscapeHtml());
                    }
                }
            }

            if (returnType == Class.class) {
                if (value != null && returnType != value.getClass()) {
                    returnType = value.getClass();
                } else {
                    continue;
                }
            }

            String str = null;

            //if (returnType != valueType) {
            FieldData fieldData = new FieldData(obj, null, value, returnType, false, fieldMapper,
                    objectDTO.level, objectDTO.set);
            objectDTO.getter = getter;
            str = object2Json(fieldData);
            //}

            if (StringUtil.isNull(str)) {
                if (fieldMapper.defaultType == JSON_INCLUDE.NON_NULL
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                    continue;

                } else {
                    str = "null";
                }

            } else if (StringUtil.isEmpty(str)) {
                if (fieldMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                    continue;
                }

                str = "null";

            } else if (fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT
                    && DefaultValue.isDefault(str, returnType)) {
                continue;
            }

            StringBuffer sb = new StringBuffer();
            sb.append(repeatedItem);
            if (fieldMapper.jsonNoName == null || !fieldMapper.jsonNoName) {
                sb.append("\"" + name + "\":" + pretty);
            }
            sb.append(str);
            sb.append(",");

            keyJsonStrings.put(lcfieldName, sb.toString());
            processedNameSet.add(name);
            fieldNames.put(lcfieldName, name.toLowerCase());
        }

        // handle @JsonAnyGetter
        if (annotationSupport) {
            for (Entry<String, Method> entry : otherMethods.entrySet()) {
                Method method = entry.getValue();
                if (ignoreModifiers(method.getModifiers(), classMapper.includeFieldsWithModifiers)) {
                    continue;
                }

                for (Annotation annotation : method.getAnnotations()) {
                    if (ignoreField(annotation, ignoreFieldsWithAnnotations)) {
                        continue;
                    }

                    if (annotation instanceof JsonValue
                            || annotation instanceof org.codehaus.jackson.annotate.JsonValue) {
                        Object mvalue = ObjectUtil.getMethodValue(obj, method);
                        if (mvalue != null) {
                            return StringUtil.doublequote(mvalue, isEscapeHtml());
                        }

                    } else if (annotation instanceof JsonAnyGetter
                            || annotation instanceof org.codehaus.jackson.annotate.JsonAnyGetter
                            || annotation instanceof ca.oson.json.annotation.FieldMapper) {

                        if (annotation instanceof ca.oson.json.annotation.FieldMapper) {
                            ca.oson.json.annotation.FieldMapper fieldMapper = (ca.oson.json.annotation.FieldMapper) annotation;

                            if (fieldMapper.jsonAnyGetter() == BOOLEAN.FALSE) {
                                continue;
                            }
                        }

                        jsonAnyGetterMethods.add(method);
                    }
                }
            }
        }

        for (Method method : jsonAnyGetterMethods) {
            if (method != null) {
                Object allValues = ObjectUtil.getMethodValue(obj, method);

                if (allValues != null && allValues instanceof Map) {
                    Map<String, Object> map = (Map) allValues;
                    String str;
                    for (String name : map.keySet()) {
                        Object value = map.get(name);

                        // java to json, check if this name is allowed or changed
                        name = java2Json(name);

                        if (!StringUtil.isEmpty(name)) {

                            FieldData newFieldData = new FieldData(value, value.getClass(), false,
                                    objectDTO.level, objectDTO.set);
                            newFieldData.defaultType = classMapper.defaultType;
                            str = object2Json(newFieldData);

                            if (StringUtil.isNull(str)) {
                                if (classMapper.defaultType == JSON_INCLUDE.NON_NULL
                                        || classMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                                        || classMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                                    continue;

                                } else {
                                    str = "null";
                                }

                            } else if (StringUtil.isEmpty(str)) {
                                if (classMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                                        || classMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                                    continue;
                                }

                                str = "null";

                            } else if (DefaultValue.isDefault(str, value.getClass())) {
                                if (classMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                                    continue;
                                }
                            }

                            StringBuffer sb = new StringBuffer();
                            sb.append(repeatedItem);
                            sb.append("\"" + name + "\":" + pretty);
                            sb.append(str);
                            sb.append(",");
                            keyJsonStrings.put(name, sb.toString());
                        }
                    }
                }
            }
        }

        int size = keyJsonStrings.size();
        if (size == 0) {
            return "{}"; // ""

        } else {
            String includeClassType = "";
            if (classMapper.includeClassTypeInJson) { //getIncludeClassTypeInJson()
                includeClassType = repeatedItem + "\"@class\":" + pretty + "\"" + valueType.getName() + "\",";
            }

            if (exposed != null && exposed.size() > 0) {
                Map<String, String> map = new LinkedHashMap<>();

                for (String key : keyJsonStrings.keySet()) {
                    if (exposed.contains(key)) {
                        map.put(key, keyJsonStrings.get(key));
                    }
                }

                keyJsonStrings = map;
            }

            if (keyJsonStrings.size() == 1 && this.isValueOnly()) {
                for (Map.Entry<String, String> entry : keyJsonStrings.entrySet()) {
                    if (entry.getKey().toLowerCase().equals("value")) {
                        String value = entry.getValue();
                        String[] values = value.split(":");
                        value = null;
                        if (values.length == 1) {
                            value = values[0];
                        } else if (values.length == 2) {
                            value = values[1];
                        }
                        if (value != null && value.length() > 1) {
                            return value.substring(0, value.length() - 1);
                        }
                    }
                }
            }

            // based on sorting requirements
            StringBuffer sb = new StringBuffer();
            if (classMapper.propertyOrders != null) {
                for (String property : classMapper.propertyOrders) {
                    property = property.toLowerCase();
                    String jsonText = keyJsonStrings.get(property);
                    if (jsonText != null) {
                        sb.append(jsonText);
                        keyJsonStrings.remove(property);
                    } else {
                        property = fieldNames.get(property);
                        if (property != null && keyJsonStrings.containsKey(property)) {
                            sb.append(keyJsonStrings.get(property));
                            keyJsonStrings.remove(property);
                        }
                    }
                }
            }

            List<String> properties = new ArrayList(keyJsonStrings.keySet());
            if (classMapper.orderByKeyAndProperties) {
                Collections.sort(properties);
            }

            for (String property : properties) {
                sb.append(keyJsonStrings.get(property));
            }

            String text = sb.toString();
            size = text.length();
            if (size == 0) {
                return "{}";
            } else {
                return "{" + includeClassType + text.substring(0, size - 1) + repeated + "}";
            }
        }

    } catch (IllegalArgumentException | SecurityException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
        // } catch (InvocationTargetException e) {
    }
}