public Map findReaders()

in johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java [558:712]


    public Map<String, Reader> findReaders(final Class<?> clazz) {
        final Map<String, Reader> readers = delegate.findReaders(clazz);

        final boolean record = isRecord(clazz) || Meta.getAnnotation(clazz, JohnzonRecord.class) != null;
        final Map<String, Parameter> recordParams = record ?
                findRecordConstructor(clazz)
                        .map(c -> Stream.of(c.getParameters())
                                .collect(toMap(p -> ofNullable(p.getAnnotation(JohnzonRecord.Name.class))
                                        .map(JohnzonRecord.Name::value)
                                        .orElseGet(p::getName), identity())))
                        .orElseGet(Collections::emptyMap) :
                null;
        final Comparator<String> keyComparator = fieldComparator(clazz);
        final Map<String, Reader> result = keyComparator == null ? new HashMap<>() : new TreeMap<>(keyComparator);
        for (final Map.Entry<String, Reader> entry : readers.entrySet()) {
            final Reader initialReader = entry.getValue();
            final DecoratedType annotations = record ? new DecoratedType() {
                private final Parameter parameter = recordParams.get(entry.getKey());

                @Override
                public Type getType() {
                    return initialReader.getType();
                }

                @Override
                public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
                    final T annotation = initialReader.getAnnotation(clazz);
                    return annotation == null && parameter != null ? parameter.getAnnotation(clazz) : annotation;
                }

                @Override
                public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
                    final T annotation = parameter == null ? null : parameter.getAnnotation(clazz);
                    return annotation == null ? initialReader.getClassOrPackageAnnotation(clazz) : annotation;
                }

                @Override
                public Adapter<?, ?> findConverter() {
                    return initialReader.findConverter();
                }

                @Override
                public boolean isNillable(final boolean globalConfig) {
                    return initialReader.isNillable(globalConfig);
                }
            } : initialReader;
            if (isTransient(initialReader, visibility, clazz, true)) {
                validateAnnotationsOnTransientField(initialReader);
                continue;
            }
            if (annotations.getAnnotation(JohnzonAny.class) != null) {
                continue;
            }

            final Reader finalReader;
            if (FieldAndMethodAccessMode.CompositeDecoratedType.class.isInstance(initialReader)) { // unwrap to use the right reader
                final FieldAndMethodAccessMode.CompositeDecoratedType decoratedType = FieldAndMethodAccessMode.CompositeDecoratedType.class.cast(initialReader);
                final DecoratedType type2 = decoratedType.getType2();
                if (MethodAccessMode.MethodReader.class.isInstance(type2)) {
                    finalReader = Reader.class.cast(type2);
                } else {
                    finalReader = initialReader;
                }
            } else {
                finalReader = initialReader;
            }

            // handle optionals since mapper is still only java 7
            final Type type;
            final Function<Object, Object> reader;
            final Type readerType = finalReader.getType();
            if (isOptional(readerType)) {
                type = ParameterizedType.class.cast(readerType).getActualTypeArguments()[0];
                reader = i -> ofNullable(finalReader.read(i)).map(o -> Optional.class.cast(o).orElse(null)).orElse(null);
            } else if (OptionalInt.class == readerType) {
                type = Integer.class;
                reader = i -> {
                    final OptionalInt optionalInt = OptionalInt.class.cast(finalReader.read(i));
                    return optionalInt == null || !optionalInt.isPresent() ? null : optionalInt.getAsInt();
                };
            } else if (OptionalLong.class == readerType) {
                type = Long.class;
                reader = i -> {
                    final OptionalLong optionalLong = OptionalLong.class.cast(finalReader.read(i));
                    return optionalLong == null || !optionalLong.isPresent() ? null : optionalLong.getAsLong();
                };
            } else if (OptionalDouble.class == readerType) {
                type = Double.class;
                reader = i -> {
                    final OptionalDouble optionalDouble = OptionalDouble.class.cast(finalReader.read(i));
                    return optionalDouble == null || !optionalDouble.isPresent() ? null : optionalDouble.getAsDouble();
                };
            } else if (isOptionalArray(finalReader)) {
                final Type optionalUnwrappedType = findOptionalType(GenericArrayType.class.cast(readerType).getGenericComponentType());
                type = new GenericArrayTypeImpl(optionalUnwrappedType);
                reader = i -> {
                    final Object[] optionals = Object[].class.cast(finalReader.read(i));
                    return optionals == null ?
                            null : Stream.of(optionals)
                            .map(Optional.class::cast)
                            .map(o -> o.orElse(null))
                            .toArray();
                };
            } else {
                type = readerType;
                reader = finalReader::read;
            }

            final WriterConverters writerConverters = new WriterConverters(annotations, types);
            final JsonbProperty property = annotations.getAnnotation(JsonbProperty.class);
            final JsonbNillable propertyNillable = annotations.getAnnotation(JsonbNillable.class);
            final JsonbNillable classOrPackageNillable = annotations.getClassOrPackageAnnotation(JsonbNillable.class);
            final boolean isNillable = isNillable(property, propertyNillable, classOrPackageNillable);
            final String key = property == null || property.value().isEmpty() ? naming.translateName(entry.getKey()) : property.value();
            if (result.put(key, new Reader() {
                @Override
                public Object read(final Object instance) {
                    return reader.apply(instance);
                }

                @Override
                public ObjectConverter.Writer<?> findObjectConverterWriter() {
                    return writerConverters.writer;
                }

                @Override
                public Type getType() {
                    return type;
                }

                @Override
                public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
                    return finalReader.getAnnotation(clazz);
                }

                @Override
                public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
                    return finalReader.getClassOrPackageAnnotation(clazz);
                }

                @Override
                public Adapter<?, ?> findConverter() {
                    return writerConverters.converter;
                }

                @Override
                public boolean isNillable(final boolean global) {
                    return isNillable;
                }
            }) != null) {
                throw new JsonbException("Ambiguous field " + key);
            }
        }
        return result;
    }