Java Code Examples for com.google.common.primitives.Primitives#wrap()

The following examples show how to use com.google.common.primitives.Primitives#wrap() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: RecordConverter.java    From guice-persist-orient with MIT License 6 votes vote down vote up
/**
 * @param result     orient record
 * @param targetType target conversion type
 * @param converter  converter object
 * @param <T>        target conversion type
 * @return converted object
 * @throws ResultConversionException if conversion is impossible
 */
@SuppressWarnings("unchecked")
public <T> T convert(final Object result, final Class<T> targetType, final ResultConverter converter) {
    // wrap primitive, because result will always be object
    final Class<T> target = Primitives.wrap(targetType);
    // do manual conversion to other types if required (usually this will be done automatically by connection
    // object, but async and live callbacks will always return documents)
    T res = tryConversion(result, target);
    if (res != null) {
        return res;
    }

    // use converter
    final ResultDescriptor desc = new ResultDescriptor();
    // support void case for more universal usage
    desc.returnType = target.equals(Void.class) ? ResultType.VOID : ResultType.PLAIN;
    desc.entityType = target;
    desc.expectType = target;
    desc.entityDbType = ORecord.class.isAssignableFrom(target) ? DbType.DOCUMENT : DbType.UNKNOWN;
    res = (T) converter.convert(desc, result);
    ResultUtils.check(res, target);
    return res;
}
 
Example 2
Source File: ConfigTreeBuilder.java    From dropwizard-guicey with MIT License 6 votes vote down vote up
@SuppressWarnings("unchecked")
private static Class correctValueType(final Class type, final boolean custom) {
    Class res = type;
    if (!custom) {
        if (type.isPrimitive()) {
            // unwrap possible primitive to always deal with objects
            res = Primitives.wrap(type);
        } else {
            // use minimal type to simplify binding
            res = MoreObjects.firstNonNull(
                    findMatchingType(type, COMMON_VALUE_TYPES),
                    res);
        }
    }
    return res;
}
 
Example 3
Source File: ReflectionUtil.java    From NOVA-Core with GNU Lesser General Public License v3.0 6 votes vote down vote up
static boolean isAssignmentCompatible(Class<?> a, Class<?> b) {
	if (a == b)
		return true;

	// Wrap primitive type
	a = Primitives.wrap(a);

	// Check primitive type assignment compatibility
	if (b.isPrimitive()) {
		b = Primitives.wrap(b);

		float distance = calculateDistancePrimitive(a, b);
		return distance >= 0;

	} else {
		return b.isInstance(b);
	}
}
 
Example 4
Source File: BuckStarlarkParam.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * @param parameter the parameter type class
 * @param namedParameter the name of the parameter, if any
 * @param defaultSkylarkValue the string represetnation of the default skylark value
 * @param noneable whether this parameter can accept `None`
 * @return an instance of the skylark annotation representing a parameter of the given type and
 *     name
 */
static BuckStarlarkParam fromParam(
    Class<?> parameter,
    @Nullable String namedParameter,
    @Nullable String defaultSkylarkValue,
    boolean noneable) {
  if (namedParameter == null) {
    namedParameter = "";
  }
  if (defaultSkylarkValue == null) {
    defaultSkylarkValue = "";
  }
  Class<?> type = parameter;
  if (type.isPrimitive()) {
    type = Primitives.wrap(type);
  }
  return new BuckStarlarkParam(namedParameter, type, defaultSkylarkValue, noneable);
}
 
Example 5
Source File: ContainerFlagField.java    From java-flagz with MIT License 6 votes vote down vote up
@SuppressWarnings("unchecked")
protected static <X> X itemFromString(String value, Class<X> clazz, Flag flag)
    throws FlagException {
  // In case we get a primitive type (e.g. from Scala), get the boxed version to know
  // how to serialize.
  clazz = Primitives.wrap(clazz);
  if (Number.class.isAssignableFrom(clazz)) {
    return clazz.cast(PrimitiveFlagField.NumberFlagField.fromString(value, clazz, flag));
  } else if (Boolean.class.isAssignableFrom(clazz)) {
    return clazz.cast(Boolean.valueOf(value));
  } else if (String.class.isAssignableFrom(clazz)) {
    return clazz.cast(value);
  } else if (clazz.isEnum()) {
    return (X) PrimitiveFlagField.EnumFlagField.fromString(value, (Class<Enum>) clazz, flag);
  }
  throw new FlagException.UnsupportedType(flag, clazz);
}
 
Example 6
Source File: BuiltInFunctionTupleFilter.java    From kylin-on-parquet-v2 with Apache License 2.0 6 votes vote down vote up
@Override
public void addChild(TupleFilter child) {
    if (child instanceof ColumnTupleFilter || child instanceof BuiltInFunctionTupleFilter) {
        columnContainerFilter = child;
        colPosition = methodParams.size();
        methodParams.add(null);
    } else if (child instanceof ConstantTupleFilter) {
        this.constantTupleFilter = (ConstantTupleFilter) child;
        Serializable constVal = (Serializable) child.getValues().iterator().next();
        try {
            constantPosition = methodParams.size();
            Class<?> clazz = Primitives.wrap(method.getParameterTypes()[methodParams.size()]);
            if (!Primitives.isWrapperType(clazz))
                methodParams.add(constVal);
            else
                methodParams.add((Serializable) clazz
                        .cast(clazz.getDeclaredMethod("valueOf", String.class).invoke(null, constVal)));
        } catch (Exception e) {
            logger.warn("Reflection failed for methodParams. ", e);
            isValidFunc = false;
        }
    }
    super.addChild(child);
}
 
Example 7
Source File: PolymorphicScalarFunction.java    From presto with Apache License 2.0 5 votes vote down vote up
private static Class<?> getNullAwareContainerType(Class<?> clazz, boolean nullable)
{
    if (nullable) {
        return Primitives.wrap(clazz);
    }
    return clazz;
}
 
Example 8
Source File: LambdaBytecodeGenerator.java    From presto with Apache License 2.0 5 votes vote down vote up
private static CompiledLambda defineLambdaMethod(
        RowExpressionCompiler innerExpressionCompiler,
        ClassDefinition classDefinition,
        String methodName,
        List<Parameter> inputParameters,
        LambdaDefinitionExpression lambda)
{
    checkCondition(inputParameters.size() <= 254, NOT_SUPPORTED, "Too many arguments for lambda expression");
    Class<?> returnType = Primitives.wrap(lambda.getBody().getType().getJavaType());
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), methodName, type(returnType), inputParameters);

    Scope scope = method.getScope();
    Variable wasNull = scope.declareVariable(boolean.class, "wasNull");
    BytecodeNode compiledBody = innerExpressionCompiler.compile(lambda.getBody(), scope);
    method.getBody()
            .putVariable(wasNull, false)
            .append(compiledBody)
            .append(boxPrimitiveIfNecessary(scope, returnType))
            .ret(returnType);

    Handle lambdaAsmHandle = new Handle(
            Opcodes.H_INVOKEVIRTUAL,
            method.getThis().getType().getClassName(),
            method.getName(),
            method.getMethodDescriptor(),
            false);

    return new CompiledLambda(
            lambdaAsmHandle,
            method.getReturnType(),
            method.getParameterTypes());
}
 
Example 9
Source File: Types.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Determine the "base type" of a field. That is, the following will be returned:
 *
 * <ul>
 *   <li>{@code String} -&gt; {@code String.class}
 *   <li>{@code Optional&lt;String&gt;} -&gt; {@code String.class}
 *   <li>{@code Set&lt;String&gt;} -&gt; {@code String.class}
 *   <li>{@code Collection&lt;? extends Comparable&gt;} -&gt; {@code Comparable.class}
 *   <li>{@code Collection&lt;? super Comparable} -&gt; {@code Object.class}
 * </ul>
 */
public static Type getBaseType(Field field) {
  Type type = getFirstNonOptionalType(field);

  if (type instanceof ParameterizedType) {
    type = ((ParameterizedType) type).getActualTypeArguments()[0];
  }

  if (type instanceof WildcardType) {
    type = ((WildcardType) type).getUpperBounds()[0];
  }

  return Primitives.wrap((Class<?>) type);
}
 
Example 10
Source File: InvokableArguments.java    From jrestless with Apache License 2.0 5 votes vote down vote up
private void checkArgumentType(int paramIndex, Object value) {
	Class<?> paramType = parameterTypes[paramIndex];
	boolean primitiveParam = paramType.isPrimitive();
	if (primitiveParam) {
		paramType = Primitives.wrap(paramType);
	}
	if (value == null && primitiveParam) {
		throw new IllegalArgumentException("primitive parameter cannot be null - index:" + paramIndex);
	} else if (value != null && !paramType.isAssignableFrom(value.getClass())) {
		throw new IllegalArgumentException("expected argument ('" + value + "') with index " + paramIndex
				+ " to be of type '" + paramType + "' but was '" + value.getClass() + "'");
	}
}
 
Example 11
Source File: EndpointMeta.java    From ameba with MIT License 5 votes vote down vote up
MessageHandlerFactory(MethodHandle method, ParameterExtractor[] extractors, Class<?> type, long maxMessageSize) {
    this.method = method;
    this.extractors = extractors;
    this.type = Primitives.isWrapperType(type)
            ? type
            : Primitives.wrap(type);
    this.maxMessageSize = maxMessageSize;
}
 
Example 12
Source File: ParamConverterEngine.java    From wisdom with Apache License 2.0 5 votes vote down vote up
private <T> T convertSingleValue(String input, Class<T> type, String defaultValue) {
    if (type.isPrimitive()) {
        type = Primitives.wrap(type);
        if (input == null && defaultValue == null) {
            defaultValue = ReflectionHelper.getPrimitiveDefault(type);
        }
    }

    ParameterConverter<T> converter = getConverter(type);
    if (input != null) {
        return converter.fromString(input);
    } else {
        return converter.fromString(defaultValue);
    }
}
 
Example 13
Source File: ParamConverterEngine.java    From wisdom with Apache License 2.0 5 votes vote down vote up
private <T> T createArray(Collection<String> input, Class<?> componentType) {
    if (input == null) {
        //noinspection unchecked
        return (T) Array.newInstance(componentType, 0);
    }

    Class<?> theType = componentType;
    if (componentType.isPrimitive()) {
        theType = Primitives.wrap(componentType);
    }

    ParameterConverter converter = getConverter(theType);

    List<Object> list = new ArrayList<>();
    for (String v : input) {
        list.add(converter.fromString(v));
    }
    // We cannot use the toArray method as the the type does not match (toArray would produce an object[]).
    Object array = Array.newInstance(componentType, list.size());
    int i = 0;
    for (Object o : list) {
        Array.set(array, i, o);
        i++;
    }

    //noinspection unchecked
    return (T) array;
}
 
Example 14
Source File: AbstractPrototyper.java    From wicket-orientdb with Apache License 2.0 5 votes vote down vote up
/**
 * Method for obtaining default value of required property
 * @param propName name of a property
 * @param returnType type of a property
 * @return default value for particular property
 */
protected Object getDefaultValue(String propName, Class<?> returnType)
{
	Object ret = null;
	if(returnType.isPrimitive())
	{
		if(returnType.equals(boolean.class))
		{
			return false;
		}
		else if(returnType.equals(char.class))
		{
			return '\0';
		}
		else
		{
			try
			{
				Class<?> wrapperClass = Primitives.wrap(returnType);
				return wrapperClass.getMethod("valueOf", String.class).invoke(null, "0");
			} catch (Throwable e)
			{
				throw new WicketRuntimeException("Can't create default value for '"+propName+"' which should have type '"+returnType.getName()+"'");
			} 
		}
	}
	return ret;
}
 
Example 15
Source File: Reflection.java    From SkyblockAddons with MIT License 5 votes vote down vote up
/**
 * Gets a method with matching return type and parameter types.
 * <p>
 * The return type and parameter types are automatically checked against assignable types and primitives.
 * <p>
 * Super classes are automatically checked.
 *
 * @param type The return type to look for.
 * @param paramTypes The types of parameters to look for.
 * @return The field with matching return type and parameter types.
 * @throws ReflectionException When the class or method cannot be located.
 */
public final MethodAccessor getMethod(Class<?> type, Class<?>... paramTypes) throws ReflectionException {
	Class<?> utype = (type.isPrimitive() ? Primitives.wrap(type) : Primitives.unwrap(type));
	Class<?>[] types = toPrimitiveTypeArray(paramTypes);

	if (METHOD_CACHE_CLASS.containsKey(this.getClazzPath())) {
		Map<Class<?>, Map<Class<?>[], MethodAccessor>> methods = METHOD_CACHE_CLASS.get(this.getClazzPath());

		if (methods.containsKey(type)) {
			Map<Class<?>[], MethodAccessor> returnTypeMethods = methods.get(type);

			for (Map.Entry<Class<?>[], MethodAccessor> entry : returnTypeMethods.entrySet()) {
				if (Arrays.equals(entry.getKey(), types)) {
					return entry.getValue();
				}
			}
		} else
			METHOD_CACHE_CLASS.get(this.getClazzPath()).put(type, new HashMap<>());
	} else {
		METHOD_CACHE_CLASS.put(this.getClazzPath(), new HashMap<>());
		METHOD_CACHE_CLASS.get(this.getClazzPath()).put(type, new HashMap<>());
	}

	for (Method method : this.getClazz().getDeclaredMethods()) {
		Class<?>[] methodTypes = toPrimitiveTypeArray(method.getParameterTypes());
		Class<?> returnType = method.getReturnType();

		if ((returnType.equals(type) || type.isAssignableFrom(returnType) || returnType.equals(utype) || utype.isAssignableFrom(returnType)) && isEqualsTypeArray(methodTypes, types)) {
			method.setAccessible(true);
			MethodAccessor methodAccessor = new MethodAccessor(this, method);
			METHOD_CACHE_CLASS.get(this.getClazzPath()).get(type).put(types, methodAccessor);
			return methodAccessor;
		}
	}

	if (this.getClazz().getSuperclass() != null)
		return this.getSuperReflection().getMethod(type, paramTypes);

	throw new ReflectionException(StringUtil.format("The method with return type {0} was not found with parameters {1}!", type, Arrays.asList(types)));
}
 
Example 16
Source File: LambdaBytecodeGenerator.java    From presto with Apache License 2.0 4 votes vote down vote up
public static BytecodeNode generateLambda(
        BytecodeGeneratorContext context,
        List<RowExpression> captureExpressions,
        CompiledLambda compiledLambda,
        Class<?> lambdaInterface)
{
    if (!lambdaInterface.isAnnotationPresent(FunctionalInterface.class)) {
        // lambdaInterface is checked to be annotated with FunctionalInterface when generating ScalarFunctionImplementation
        throw new VerifyException("lambda should be generated as class annotated with FunctionalInterface");
    }

    BytecodeBlock block = new BytecodeBlock().setDescription("Partial apply");
    Scope scope = context.getScope();

    Variable wasNull = scope.getVariable("wasNull");

    // generate values to be captured
    ImmutableList.Builder<BytecodeExpression> captureVariableBuilder = ImmutableList.builder();
    for (RowExpression captureExpression : captureExpressions) {
        Class<?> valueType = Primitives.wrap(captureExpression.getType().getJavaType());
        Variable valueVariable = scope.createTempVariable(valueType);
        block.append(context.generate(captureExpression));
        block.append(boxPrimitiveIfNecessary(scope, valueType));
        block.putVariable(valueVariable);
        block.append(wasNull.set(constantFalse()));
        captureVariableBuilder.add(valueVariable);
    }

    List<BytecodeExpression> captureVariables = ImmutableList.<BytecodeExpression>builder()
            .add(scope.getThis(), scope.getVariable("session"))
            .addAll(captureVariableBuilder.build())
            .build();

    Type instantiatedMethodAsmType = getMethodType(
            compiledLambda.getReturnType().getAsmType(),
            compiledLambda.getParameterTypes().stream()
                    .skip(captureExpressions.size() + 1) // skip capture variables and ConnectorSession
                    .map(ParameterizedType::getAsmType)
                    .collect(toImmutableList()).toArray(new Type[0]));

    block.append(
            invokeDynamic(
                    LAMBDA_CAPTURE_METHOD,
                    ImmutableList.of(
                            getType(getSingleApplyMethod(lambdaInterface)),
                            compiledLambda.getLambdaAsmHandle(),
                            instantiatedMethodAsmType),
                    "apply",
                    type(lambdaInterface),
                    captureVariables));
    return block;
}
 
Example 17
Source File: ParametricScalarImplementation.java    From presto with Apache License 2.0 4 votes vote down vote up
private static MethodType javaMethodType(ParametricScalarImplementationChoice choice, Signature signature, Metadata metadata)
{
    // This method accomplishes two purposes:
    // * Assert that the method signature is as expected.
    //   This catches errors that would otherwise surface during bytecode generation and class loading.
    // * Adapt the method signature when necessary (for example, when the parameter type or return type is declared as Object).
    ImmutableList.Builder<Class<?>> methodHandleParameterTypes = ImmutableList.builder();
    if (choice.getConstructor().isPresent()) {
        methodHandleParameterTypes.add(Object.class);
    }
    if (choice.hasConnectorSession()) {
        methodHandleParameterTypes.add(ConnectorSession.class);
    }

    List<ArgumentProperty> argumentProperties = choice.getArgumentProperties();
    for (int i = 0; i < argumentProperties.size(); i++) {
        ArgumentProperty argumentProperty = argumentProperties.get(i);
        switch (argumentProperty.getArgumentType()) {
            case VALUE_TYPE:
                Type signatureType = metadata.getType(signature.getArgumentTypes().get(i));
                switch (argumentProperty.getNullConvention()) {
                    case RETURN_NULL_ON_NULL:
                        methodHandleParameterTypes.add(signatureType.getJavaType());
                        break;
                    case USE_NULL_FLAG:
                        methodHandleParameterTypes.add(signatureType.getJavaType());
                        methodHandleParameterTypes.add(boolean.class);
                        break;
                    case USE_BOXED_TYPE:
                        methodHandleParameterTypes.add(Primitives.wrap(signatureType.getJavaType()));
                        break;
                    case BLOCK_AND_POSITION:
                        methodHandleParameterTypes.add(Block.class);
                        methodHandleParameterTypes.add(int.class);
                        break;
                    default:
                        throw new UnsupportedOperationException("unknown NullConvention");
                }
                break;
            case FUNCTION_TYPE:
                methodHandleParameterTypes.add(argumentProperty.getLambdaInterface().orElseThrow(() -> new IllegalArgumentException("Argument is not a function")));
                break;
            default:
                throw new UnsupportedOperationException("unknown ArgumentType");
        }
    }

    Class<?> methodHandleReturnType = metadata.getType(signature.getReturnType()).getJavaType();
    if (choice.isNullable()) {
        methodHandleReturnType = Primitives.wrap(methodHandleReturnType);
    }

    return MethodType.methodType(methodHandleReturnType, methodHandleParameterTypes.build());
}
 
Example 18
Source File: Utils.java    From mobly-bundled-snippets with Apache License 2.0 4 votes vote down vote up
/**
 * Simplified API to invoke an instance method by reflection.
 *
 * <p>Sample usage:
 *
 * <pre>
 *   boolean result = (boolean) Utils.invokeByReflection(
 *           mWifiManager,
 *           "setWifiApEnabled", null /* wifiConfiguration * /, true /* enabled * /);
 * </pre>
 *
 * @param instance Instance of object defining the method to call.
 * @param methodName Name of the method to call. Can be inherited.
 * @param args Variadic array of arguments to supply to the method. Their types will be used to
 *     locate a suitable method to call. Subtypes, primitive types, boxed types, and {@code
 *     null} arguments are properly handled.
 * @return The return value of the method, or {@code null} if no return value.
 * @throws NoSuchMethodException If no suitable method could be found.
 * @throws Throwable The exception raised by the method, if any.
 */
public static Object invokeByReflection(Object instance, String methodName, Object... args)
        throws Throwable {
    // Java doesn't know if invokeByReflection(instance, name, null) means that the array is
    // null or that it's a non-null array containing a single null element. We mean the latter.
    // Silly Java.
    if (args == null) {
        args = new Object[] {null};
    }
    // Can't use Class#getMethod(Class<?>...) because it expects that the passed in classes
    // exactly match the parameters of the method, and doesn't handle superclasses.
    Method method = null;
    METHOD_SEARCHER:
    for (Method candidateMethod : instance.getClass().getMethods()) {
        // getMethods() returns only public methods, so we don't need to worry about checking
        // whether the method is accessible.
        if (!candidateMethod.getName().equals(methodName)) {
            continue;
        }
        Class<?>[] declaredParams = candidateMethod.getParameterTypes();
        if (declaredParams.length != args.length) {
            continue;
        }
        for (int i = 0; i < declaredParams.length; i++) {
            if (args[i] == null) {
                // Null is assignable to anything except primitives.
                if (declaredParams[i].isPrimitive()) {
                    continue METHOD_SEARCHER;
                }
            } else {
                // Allow autoboxing during reflection by wrapping primitives.
                Class<?> declaredClass = Primitives.wrap(declaredParams[i]);
                Class<?> actualClass = Primitives.wrap(args[i].getClass());
                TypeToken<?> declaredParamType = TypeToken.of(declaredClass);
                TypeToken<?> actualParamType = TypeToken.of(actualClass);
                if (!declaredParamType.isSupertypeOf(actualParamType)) {
                    continue METHOD_SEARCHER;
                }
            }
        }
        method = candidateMethod;
        break;
    }
    if (method == null) {
        StringBuilder methodString =
                new StringBuilder(instance.getClass().getName())
                        .append('#')
                        .append(methodName)
                        .append('(');
        for (int i = 0; i < args.length - 1; i++) {
            methodString.append(args[i].getClass().getSimpleName()).append(", ");
        }
        if (args.length > 0) {
            methodString.append(args[args.length - 1].getClass().getSimpleName());
        }
        methodString.append(')');
        throw new NoSuchMethodException(methodString.toString());
    }
    try {
        Object result = method.invoke(instance, args);
        return result;
    } catch (InvocationTargetException e) {
        throw e.getCause();
    }
}
 
Example 19
Source File: DefaultTypeCoercerFactory.java    From buck with Apache License 2.0 4 votes vote down vote up
@SuppressWarnings("unchecked")
private <T> TypeCoercer<?, ?> typeCoercerForTypeUnchecked(TypeToken<T> typeToken) {
  Type type = typeToken.getType();
  if (type instanceof TypeVariable) {
    type = ((TypeVariable<?>) type).getBounds()[0];
    if (Object.class.equals(type)) {
      throw new IllegalArgumentException("Generic types must be specific: " + type);
    }
  }

  if (type instanceof WildcardType) {
    type = ((WildcardType) type).getUpperBounds()[0];
    if (Object.class.equals(type)) {
      throw new IllegalArgumentException("Generic types must be specific: " + type);
    }
  }

  if (type instanceof Class) {
    Class<?> rawClass = Primitives.wrap((Class<?>) type);

    if (rawClass.isEnum()) {
      return enumCoercer(rawClass);
    }

    TypeCoercer<Object, ?> selectedTypeCoercer = null;
    for (TypeCoercer<Object, ?> typeCoercer : nonParameterizedTypeCoercers) {
      if (rawClass.isAssignableFrom(typeCoercer.getOutputType().getRawType())) {
        if (selectedTypeCoercer == null) {
          selectedTypeCoercer = typeCoercer;
        } else {
          throw new IllegalArgumentException("multiple coercers matched for type: " + type);
        }
      }
    }
    if (selectedTypeCoercer == null
        && DataTransferObject.class.isAssignableFrom(rawClass)
        && Types.getSupertypes(rawClass).stream()
            .anyMatch(c -> c.getAnnotation(RuleArg.class) != null)) {
      selectedTypeCoercer =
          new ImmutableTypeCoercer<>(
              getConstructorArgDescriptor((Class<? extends DataTransferObject>) rawClass));
    }
    if (selectedTypeCoercer != null) {
      return selectedTypeCoercer;
    } else {
      throw new IllegalArgumentException("no type coercer for type: " + type);
    }
  } else if (type instanceof ParameterizedType) {
    ParameterizedType parameterizedType = (ParameterizedType) type;
    return typeCoercerForParameterizedType(
        type.toString(),
        parameterizedType.getRawType(),
        parameterizedType.getActualTypeArguments());
  } else {
    throw new IllegalArgumentException("Cannot create type coercer for type: " + type);
  }
}
 
Example 20
Source File: MapFilterFunction.java    From presto with Apache License 2.0 4 votes vote down vote up
private static MethodHandle generateFilter(MapType mapType)
{
    CallSiteBinder binder = new CallSiteBinder();
    Type keyType = mapType.getKeyType();
    Type valueType = mapType.getValueType();
    Class<?> keyJavaType = Primitives.wrap(keyType.getJavaType());
    Class<?> valueJavaType = Primitives.wrap(valueType.getJavaType());

    ClassDefinition definition = new ClassDefinition(
            a(PUBLIC, FINAL),
            makeClassName("MapFilter"),
            type(Object.class));
    definition.declareDefaultConstructor(a(PRIVATE));

    Parameter state = arg("state", Object.class);
    Parameter block = arg("block", Block.class);
    Parameter function = arg("function", BinaryFunctionInterface.class);
    MethodDefinition method = definition.declareMethod(
            a(PUBLIC, STATIC),
            "filter",
            type(Block.class),
            ImmutableList.of(state, block, function));

    BytecodeBlock body = method.getBody();
    Scope scope = method.getScope();
    Variable positionCount = scope.declareVariable(int.class, "positionCount");
    Variable position = scope.declareVariable(int.class, "position");
    Variable pageBuilder = scope.declareVariable(PageBuilder.class, "pageBuilder");
    Variable mapBlockBuilder = scope.declareVariable(BlockBuilder.class, "mapBlockBuilder");
    Variable singleMapBlockWriter = scope.declareVariable(BlockBuilder.class, "singleMapBlockWriter");
    Variable keyElement = scope.declareVariable(keyJavaType, "keyElement");
    Variable valueElement = scope.declareVariable(valueJavaType, "valueElement");
    Variable keep = scope.declareVariable(Boolean.class, "keep");

    // invoke block.getPositionCount()
    body.append(positionCount.set(block.invoke("getPositionCount", int.class)));

    // prepare the single map block builder
    body.append(pageBuilder.set(state.cast(PageBuilder.class)));
    body.append(new IfStatement()
            .condition(pageBuilder.invoke("isFull", boolean.class))
            .ifTrue(pageBuilder.invoke("reset", void.class)));
    body.append(mapBlockBuilder.set(pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, constantInt(0))));
    body.append(singleMapBlockWriter.set(mapBlockBuilder.invoke("beginBlockEntry", BlockBuilder.class)));

    SqlTypeBytecodeExpression keySqlType = constantType(binder, keyType);
    BytecodeNode loadKeyElement;
    if (!keyType.equals(UNKNOWN)) {
        // key element must be non-null
        loadKeyElement = new BytecodeBlock().append(keyElement.set(keySqlType.getValue(block, position).cast(keyJavaType)));
    }
    else {
        loadKeyElement = new BytecodeBlock().append(keyElement.set(constantNull(keyJavaType)));
    }

    SqlTypeBytecodeExpression valueSqlType = constantType(binder, valueType);
    BytecodeNode loadValueElement;
    if (!valueType.equals(UNKNOWN)) {
        loadValueElement = new IfStatement()
                .condition(block.invoke("isNull", boolean.class, add(position, constantInt(1))))
                .ifTrue(valueElement.set(constantNull(valueJavaType)))
                .ifFalse(valueElement.set(valueSqlType.getValue(block, add(position, constantInt(1))).cast(valueJavaType)));
    }
    else {
        loadValueElement = new BytecodeBlock().append(valueElement.set(constantNull(valueJavaType)));
    }

    body.append(new ForLoop()
            .initialize(position.set(constantInt(0)))
            .condition(lessThan(position, positionCount))
            .update(incrementVariable(position, (byte) 2))
            .body(new BytecodeBlock()
                    .append(loadKeyElement)
                    .append(loadValueElement)
                    .append(keep.set(function.invoke("apply", Object.class, keyElement.cast(Object.class), valueElement.cast(Object.class)).cast(Boolean.class)))
                    .append(new IfStatement("if (keep != null && keep) ...")
                            .condition(and(notEqual(keep, constantNull(Boolean.class)), keep.cast(boolean.class)))
                            .ifTrue(new BytecodeBlock()
                                    .append(keySqlType.invoke("appendTo", void.class, block, position, singleMapBlockWriter))
                                    .append(valueSqlType.invoke("appendTo", void.class, block, add(position, constantInt(1)), singleMapBlockWriter))))));

    body.append(mapBlockBuilder
            .invoke("closeEntry", BlockBuilder.class)
            .pop());
    body.append(pageBuilder.invoke("declarePosition", void.class));
    body.append(constantType(binder, mapType)
            .invoke(
                    "getObject",
                    Object.class,
                    mapBlockBuilder.cast(Block.class),
                    subtract(mapBlockBuilder.invoke("getPositionCount", int.class), constantInt(1)))
            .ret());

    Class<?> generatedClass = defineClass(definition, Object.class, binder.getBindings(), MapFilterFunction.class.getClassLoader());
    return methodHandle(generatedClass, "filter", Object.class, Block.class, BinaryFunctionInterface.class);
}