com.fasterxml.jackson.databind.introspect.BasicBeanDescription#ru.vyarus.java.generics.resolver.context.GenericsContext源码实例Demo

下面列出了com.fasterxml.jackson.databind.introspect.BasicBeanDescription#ru.vyarus.java.generics.resolver.context.GenericsContext 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: dropwizard-guicey   文件: ConfigTreeBuilder.java
/**
 * Cases:
 * <ul>
 * <li>Type declared in class and used as is: resolve generics directly from type</li>
 * <li>Type declared, but lower type used (e.g. collection impl declared): track lower type generics</li>
 * <li>Type is Object: resolve generics from declaration (lower type available when value provided)</li>
 * </ul>.
 *
 * @param genericsContext generics context
 * @param type            declared property type
 * @param typeClass       type's class
 * @param objectDeclared  declared type is not Object
 * @param lowerType       selected type from declaration (maybe lower then declared or comletely taken from value)
 * @return lower type generics or empty list
 */
private static List<Type> resolveLowerGenerics(final GenericsContext genericsContext,
                                               final Type type,
                                               final Class typeClass,
                                               final boolean objectDeclared,
                                               final Class lowerType) {
    final List<Type> res;
    if (!objectDeclared && !lowerType.equals(typeClass)) {
        // case: collection declared, but not interface.. going to lower type
        res = genericsContext.inlyingType(type).type(lowerType).genericTypes();
    } else {
        // normal case: type analyzed directly
        res = genericsContext.resolveTypeGenerics(objectDeclared ? lowerType : type);
    }
    return res;
}
 
源代码2 项目: dropwizard-guicey   文件: ConfigTreeBuilder.java
/**
 * Cases:
 * <ul>
 * <li>Object declared in class: nowere to get generics, resolving from type definition</li>
 * <li>Track type generics from declared generics (may not recover all, in this case generics declaration
 * would be used)</li>
 * </ul>.
 * Note that lowerType == upperType case checked outside.
 *
 * @param genericsContext generics context
 * @param type            declared property type
 * @param objectDeclared  declared type is not Object
 * @param upperType       value type (if value available) or declaration type (from class; may be upper then
 *                        lowerType in case of collection)
 * @return upper type generics or empty list
 */
private static List<Type> resolveUpperGenerics(final GenericsContext genericsContext,
                                               final Type type,
                                               final boolean objectDeclared,
                                               final Class upperType) {
    final List<Type> res;
    if (objectDeclared) {
        // no generics declared in class - use raw generics (from type declaration)
        res = genericsContext.resolveTypeGenerics(upperType);
    } else {
        // computing from actual generic type because it may contain generics, not required for lower type
        // e.g. declaration is ExtraList<String, Integer>  lower type will be List<String>
        // but we need to preserve full generics info for upper type
        res = genericsContext.inlyingTypeAs(type, upperType).genericTypes();
    }
    return res;
}
 
源代码3 项目: dropwizard-guicey   文件: JerseyBinding.java
/**
 * Binds jersey specific component (component implements jersey interface or extends class).
 * Specific binding is required for types directly supported by jersey (e.g. ExceptionMapper).
 * Such types must be bound to target interface directly, otherwise jersey would not be able to resolve them.
 * <p> If type is {@link JerseyManaged}, binds directly.
 * Otherwise, use guice "bridge" factory to lazily bind type.</p>
 *
 * @param binder        jersey binder
 * @param injector      guice injector
 * @param type          type which implements specific jersey interface or extends class
 * @param specificType  specific jersey type (interface or abstract class)
 * @param jerseyManaged true if bean must be managed by jersey, false to bind guice managed instance
 * @param singleton     true to force singleton scope
 */
public static void bindSpecificComponent(final AbstractBinder binder,
                                         final Injector injector,
                                         final Class<?> type,
                                         final Class<?> specificType,
                                         final boolean jerseyManaged,
                                         final boolean singleton) {
    // resolve generics of specific type
    final GenericsContext context = GenericsResolver.resolve(type).type(specificType);
    final List<Type> genericTypes = context.genericTypes();
    final Type[] generics = genericTypes.toArray(new Type[0]);
    final Type bindingType = generics.length > 0 ? new ParameterizedTypeImpl(specificType, generics)
            : specificType;
    if (jerseyManaged) {
        optionalSingleton(
                binder.bind(type).to(type).to(bindingType),
                singleton);
    } else {
        optionalSingleton(
                binder.bindFactory(new GuiceComponentFactory<>(injector, type)).to(type).to(bindingType),
                singleton);
    }
}
 
/**
 * Analyze target bean methods, finding all matching (by parameters) methods.
 * If method name was specified, only methods with the same name resolved.
 *
 * @param target target bean type
 * @param params repository method params
 * @param hint   method name hint (may be null)
 * @return descriptor of all matching methods
 */
private static List<MatchedMethod> findPossibleMethods(final List<Class<?>> params, final Class<?> target,
                                                       final String hint) {
    final List<MatchedMethod> possibilities = Lists.newArrayList();
    // use generics to enforce type checks
    final GenericsContext targetGenerics = GenericsResolver.resolve(target);
    for (Method method : target.getMethods()) {
        // method hint force to check only methods with this name
        final boolean methodHintValid = hint == null || method.getName().equals(hint);
        if (!isAcceptableMethod(method) || !methodHintValid) {
            continue;
        }
        final MatchedMethod matched = analyzeMethod(method, params, targetGenerics);
        if (matched != null) {
            possibilities.add(matched);
        }
    }
    return possibilities;
}
 
@SuppressWarnings({"unchecked", "PMD.AvoidInstantiatingObjectsInLoops"})
private static MatchedMethod analyzeMethod(final Method method, final List<Class<?>> params,
                                           final GenericsContext targetGenerics) {
    final List<ParamInfo> ordinalParamsInfo = Lists.newArrayList();
    final List<Class<?>> types = targetGenerics.method(method).resolveParameters();
    final Annotation[][] annotations = method.getParameterAnnotations();
    boolean extended = false;
    for (int i = 0; i < types.size(); i++) {
        // ignore extensions (they always add value)
        try {
            if (ExtUtils.findParameterExtension(annotations[i]) == null) {
                ordinalParamsInfo.add(new ParamInfo(i, types.get(i)));
            } else {
                extended = true;
            }
        } catch (Exception ex) {
            throw new IllegalStateException(String.format("Error analysing method %s parameter %s",
                    RepositoryUtils.methodToString(method), i), ex);
        }
    }
    MatchedMethod res = null;
    if (isParametersCompatible(params, ordinalParamsInfo)) {
        res = new MatchedMethod(method, ordinalParamsInfo, extended);
    }
    return res;
}
 
源代码6 项目: generics-resolver   文件: GenericInfoUtils.java
/**
 * Type analysis in context of analyzed type. For example, resolution of field type class in context of
 * analyzed class (so we can correctly resolve it's generics).In essence, the only difference with usual type
 * resolution is known root generics.
 * <p>
 * The result is not intended to be cached as it's context-sensitive.
 *
 * @param context       generics context of containing class
 * @param type          type to analyze (important: this must be generified type and not raw class in
 *                      order to properly resolve generics)
 * @param ignoreClasses classes to exclude from hierarchy analysis
 * @return analyzed type generics info
 */
public static GenericsInfo create(
        final GenericsContext context, final Type type, final Class<?>... ignoreClasses) {
    // root generics are required only to properly solve type
    final Map<String, Type> rootGenerics = context.visibleGenericsMap();
    // first step: solve type to replace transitive generics with direct values
    final Type actual = GenericsUtils.resolveTypeVariables(type, rootGenerics);
    final Class<?> target = context.resolveClass(actual);

    LinkedHashMap<String, Type> generics = GenericsResolutionUtils.resolveGenerics(actual, rootGenerics);
    generics = GenericsResolutionUtils
            .fillOuterGenerics(actual, generics, context.getGenericsInfo().getTypesMap());
    return create(target, generics,
            // store possible owner types from parent context
            usePossiblyOwnerGenerics(target, context.getGenericsInfo()), ignoreClasses);
}
 
源代码7 项目: dropwizard-guicey   文件: ConfigTreeBuilder.java
/**
 * Create item for property.
 * <p>
 * Almost always property declaration type is used as binding type (for future binding), but:
 * <ul>
 * <li>If property type is collection implementation, then collection interface used instead</li>
 * <li>If property is Object then type would be taken from value. This means binding type will be Object
 * when value null and actual type when value provided. Assuming this case will not happen (bad config).</li>
 * </ul>
 *
 * @param root            root property (containing), may be null for roots
 * @param prop            jackson property descriptor
 * @param value           property value, may be null
 * @param genericsContext generics context
 * @return path item object
 */
private static ConfigPath createItem(final ConfigPath root,
                                     final BeanPropertyDefinition prop,
                                     final Object value,
                                     final GenericsContext genericsContext) {
    // need generified type to resolve generics manually because jackson's generics resolution
    // couldn't handle all required cases
    final Type type = prop.getGetter() != null
            ? prop.getGetter().getAnnotated().getGenericReturnType()
            : prop.getField().getAnnotated().getGenericType();
    final Class typeClass = Primitives.wrap(genericsContext.resolveClass(type));

    // upper possible known type (for introspection): ideally type of actually used configuration value
    // note that even when value is null upper type could be different from lower type due to collection projection
    final Class upperType = value == null ? typeClass : value.getClass();
    final boolean customType = isCustomType(upperType);
    // either class declaration or value type (in both cases could be projected to collection interface)
    final boolean objectDeclared = Object.class.equals(typeClass);
    final Class lowerType = correctValueType(objectDeclared ? upperType : typeClass, customType);

    final List<Type> lowerGenerics =
            resolveLowerGenerics(genericsContext, type, typeClass, objectDeclared, lowerType);
    final List<Type> upperGenerics = lowerType.equals(upperType) ? lowerGenerics
            : resolveUpperGenerics(genericsContext, type, objectDeclared, upperType);

    return new ConfigPath(
            root,
            prop.getAccessor().getDeclaringClass(),
            lowerType,
            // as an example, enum constant type could lead to anonymous class
            upperType.isAnonymousClass() ? lowerType : upperType,
            lowerGenerics,
            upperGenerics,
            fullPath(root, prop),
            value,
            customType,
            objectDeclared);
}
 
源代码8 项目: guice-persist-orient   文件: ElAnalyzer.java
/**
 * Analyze query string for variables.
 *
 * @param genericsContext generics context (set to the method owner type)
 * @param query           query string
 * @return descriptor object if variables found, null otherwise
 */
public static ElDescriptor analyzeQuery(final GenericsContext genericsContext, final String query) {
    final List<String> vars = ElUtils.findVars(query);
    ElDescriptor descriptor = null;
    if (!vars.isEmpty()) {
        descriptor = new ElDescriptor(vars);
        checkGenericVars(descriptor, genericsContext);
    }
    return descriptor;
}
 
源代码9 项目: guice-persist-orient   文件: ElAnalyzer.java
private static void checkGenericVars(final ElDescriptor descriptor, final GenericsContext generics) {
    if (generics != null) {
        for (Map.Entry<String, Type> entry : generics.genericsMap().entrySet()) {
            final String key = entry.getKey();
            if (descriptor.vars.contains(key)) {
                // using just class name, because orient don't need package
                descriptor.directValues.put(key, generics.resolveClass(entry.getValue()).getSimpleName());
            }
        }
    }
}
 
源代码10 项目: generics-resolver   文件: GenericsTrackingUtils.java
private static Type[] alignParametrizationArguments(final Class<?> exactActualType,
                                                    final Class<?> knownGenericType,
                                                    final ParameterizedType knownGeneric,
                                                    final LinkedHashMap<String, Type> knownGenerics) {

    final Type[] knownArguments;

    // if base types are equal we can match types in parametrization
    if (exactActualType.equals(knownGenericType)) {
        knownArguments = knownGeneric.getActualTypeArguments();
    } else {
        // known generic type is a subclass of resolved root type.. inception!
        // trying to track generics
        if (knownGenericType.isAssignableFrom(exactActualType)) {
            // Actual type is higher then declared in generic: need to analyze this mismatch
            // (again not known root generics and known generics in sub type)
            final LinkedHashMap<String, Type> sub = track(exactActualType, knownGenericType,
                    GenericsResolutionUtils.resolveGenerics(knownGeneric, knownGenerics));
            knownArguments = sub.values().toArray(new Type[0]);
        } else {
            // actual class, resolved in root class hierarchy is a subtype of known generic type
            // building hierarchy for known generic value class and look generics of required subclass
            final GenericsContext ctx = GenericsResolver.resolve(knownGenericType);
            knownArguments = GenericInfoUtils.create(ctx, knownGeneric)
                    .getTypeGenerics(exactActualType).values().toArray(new Type[0]);
        }
    }
    return knownArguments;
}
 
源代码11 项目: dropwizard-guicey   文件: ConfigTreeBuilder.java
/**
 * Use jackson serialization api to extract all configuration values with paths from configuration object.
 * Always analyze types, even if actual branch is not present at all (null value) in order to always bind
 * nulls and avoid "Schrodinger's binding" case. In short, bindings should not depend on configuration values
 * (presence).
 * <p>
 * Still, bindings may vary: for example, bound implementations may differ (best example is dropwizard server type),
 * as a consequences, parsed type may be different and so different properties paths could be recognized.
 *
 * @param config  jackson serialization config
 * @param content currently parsed paths
 * @param type    analyzed part type
 * @param object  analyzed part instance (may be null)
 * @return all configuration paths values
 */
@SuppressWarnings("checkstyle:CyclomaticComplexity")
private static List<ConfigPath> resolvePaths(final SerializationConfig config,
                                             final ConfigPath root,
                                             final List<ConfigPath> content,
                                             final Class type,
                                             final Object object,
                                             final GenericsContext genericsContext) {
    final BasicBeanDescription description = config.introspect(
            config.constructType(type)
    );

    for (BeanPropertyDefinition prop : description.findProperties()) {
        // ignore write-only or groovy special property
        if (!prop.couldSerialize() || prop.getName().equals("metaClass")) {
            continue;
        }
        final Object value;
        // if configuration doesn't expect serialization and throws error on access
        // (like netflix dynamic properties) it should not break app startup
        try {
            value = readValue(prop.getAccessor(), object);
        } catch (Exception ex) {
            LOGGER.warn("Can't bind configuration path '{}' due to {}: {}. Enable debug logs to see "
                            + "complete stack trace or use @JsonIgnore on property getter.",
                    fullPath(root, prop), ex.getClass().getSimpleName(), ex.getMessage());
            LOGGER.debug("Complete error: ", ex);
            continue;
        }

        final ConfigPath item = createItem(root, prop, value, genericsContext);
        content.add(item);
        if (root != null) {
            root.getChildren().add(item);
        }

        if (item.isCustomType() && !detectRecursion(item)) {
            // build generics context for actual value type (if not null)
            final GenericsContext subContext = prop.getGetter() != null
                    ? genericsContext.method(prop.getGetter().getAnnotated()).returnTypeAs(item.getValueType())
                    : genericsContext.fieldTypeAs(prop.getField().getAnnotated(), item.getValueType());

            resolvePaths(config, item, content, item.getValueType(),
                    item.getValue(), subContext);
        }
    }
    if (root != null) {
        // simple properties goes up and composite objects go lower (both groups sorted alphabetically)
        root.getChildren().sort(Comparator.comparing(o -> (o.isCustomType() ? 'b' : 'a') + o.getPath()));
    }
    return content;
}
 
源代码12 项目: generics-resolver   文件: GenericInfoUtils.java
/**
 * Type analysis in context of analyzed type with child class as target type. Case: we have interface
 * (or base type) with generic in class (as field or return type), but we need to analyze actual
 * instance type (from value). This method will analyze type from new root (where generics are unknown), but
 * will add known middle generics.
 * <p>
 * NOTE: some of the root generics could possibly be resolved if there are any traceable connectivity between
 * the root class and known middle generics. All possible (known) cases should be solved. For example,
 * {@code Root<K> extends Target<List<K>>} when we know {@code Target<Collection<String>>} then
 * K will be tracked as String.
 * <p>
 * In essence: root generics are partially resolved by tracking definition from known middle class.
 * Other root generics resolved as upper bound (the same as in usual type resolution case).
 * If middle type generic is not specified (and so resolved as Object) then known specific type used
 * (assuming root type would be used in place with known parametrization and so more specifi generic may be
 * counted).
 * <p>
 * The result is not intended to be cached as it's context-sensitive.
 *
 * @param context       generics context of containing class
 * @param type          type to analyze (important: this must be generified type and not raw class in
 *                      order to properly resolve generics)
 * @param asType        target child type (this class contain original type in hierarchy)
 * @param ignoreClasses classes to exclude from hierarchy analysis
 * @return analyzed type generics info
 */
public static GenericsInfo create(final GenericsContext context,
                                  final Type type,
                                  final Class<?> asType,
                                  final Class<?>... ignoreClasses) {
    // root generics are required only to properly solve type
    final Map<String, Type> rootGenerics = context.visibleGenericsMap();
    // first step: solve type to replace transitive generics with direct values
    final Type actual = GenericsUtils.resolveTypeVariables(type, rootGenerics);
    final Class<?> middleType = context.resolveClass(actual);
    if (!middleType.isAssignableFrom(asType)) {
        throw new IllegalArgumentException(String.format("Requested type %s is not a subtype of %s",
                TypeToStringUtils.toStringType(asType), TypeToStringUtils.toStringType(middleType)));
    }

    // known middle type
    LinkedHashMap<String, Type> typeGenerics = GenericsResolutionUtils.resolveGenerics(actual, rootGenerics);
    final Map<Class<?>, LinkedHashMap<String, Type>> knownGenerics =
            new HashMap<Class<?>, LinkedHashMap<String, Type>>();
    // field could be declared as (Outer<String>.Inner field) and already contain actual outer generics
    knownGenerics.put(middleType, GenericsResolutionUtils
            .fillOuterGenerics(actual, typeGenerics, context.getGenericsInfo().getTypesMap()));
    if (TypeUtils.isInner(middleType)) {
        // remember possibly specified outer generics (they were already resolved above)
        knownGenerics.put((Class) TypeUtils.getOuter(middleType), new LinkedHashMap<String, Type>(
                GenericsUtils.extractOwnerGenerics(middleType, knownGenerics.get(middleType))));
    } else {
        // store other types for possible outer classes generics resolution
        knownGenerics.putAll(usePossiblyOwnerGenerics(asType, context.getGenericsInfo()));
    }


    // root type
    typeGenerics = asType.getTypeParameters().length > 0
            ? GenericsTrackingUtils.track(asType, middleType, typeGenerics)
            : EmptyGenericsMap.getInstance();

    typeGenerics = GenericsResolutionUtils
            .fillOuterGenerics(asType, typeGenerics, knownGenerics.size() > 1
                    // if known middle type is inner class then owner already filled
                    ? knownGenerics : context.getGenericsInfo().getTypesMap());
    return create(asType, typeGenerics, knownGenerics, ignoreClasses);
}
 
源代码13 项目: generics-resolver   文件: GenericsResolver.java
/**
 * By default returned context set on root class (but generic types for root class will be resolved from specified
 * generics bounds). To use it switch context to required type from hierarchy:
 * {@code returnedContext.type(SomeTypeFromHierarchy.class)}.
 * <p>
 * Note: when ignore classes provided, produced {@code GenericsInfo} instance will not be cached
 * (and full version from cache will not be used also)
 *
 * @param type          root class to resolve generics hierarchy
 * @param ignoreClasses list of classes to ignore during inspection (useful to avoid interface clashes
 *                      or to limit resolution depth)
 * @return resolved generics context object
 */
public static GenericsContext resolve(final Class<?> type, final Class<?>... ignoreClasses) {
    final Class<?> notPrimitiveType = TypeUtils.wrapPrimitive(type);
    return new GenericsContext(
            GenericsInfoFactory.create(notPrimitiveType, ignoreClasses), notPrimitiveType);
}