| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package freemarker.ext.beans; |
| |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * Flag values and masks for "type flags". "Type flags" is a set of bits that store information about the possible |
| * destination types at a parameter position of overloaded methods. |
| */ |
| class TypeFlags { |
| |
| /** |
| * Indicates that the unwrapping hint will not be a specific numerical type; it must not be set if there's no |
| * numerical type at the given parameter index. |
| */ |
| static final int WIDENED_NUMERICAL_UNWRAPPING_HINT = 1; |
| |
| static final int BYTE = 4; |
| static final int SHORT = 8; |
| static final int INTEGER = 16; |
| static final int LONG = 32; |
| static final int FLOAT = 64; |
| static final int DOUBLE = 128; |
| static final int BIG_INTEGER = 256; |
| static final int BIG_DECIMAL = 512; |
| static final int UNKNOWN_NUMERICAL_TYPE = 1024; |
| |
| static final int ACCEPTS_NUMBER = 0x800; |
| static final int ACCEPTS_DATE = 0x1000; |
| static final int ACCEPTS_STRING = 0x2000; |
| static final int ACCEPTS_BOOLEAN = 0x4000; |
| static final int ACCEPTS_MAP = 0x8000; |
| static final int ACCEPTS_LIST = 0x10000; |
| static final int ACCEPTS_SET = 0x20000; |
| static final int ACCEPTS_ARRAY = 0x40000; |
| |
| /** |
| * Indicates the presence of the char or Character type |
| */ |
| static final int CHARACTER = 0x80000; |
| |
| static final int ACCEPTS_ANY_OBJECT = ACCEPTS_NUMBER | ACCEPTS_DATE | ACCEPTS_STRING | ACCEPTS_BOOLEAN |
| | ACCEPTS_MAP | ACCEPTS_LIST | ACCEPTS_SET | ACCEPTS_ARRAY; |
| |
| static final int MASK_KNOWN_INTEGERS = BYTE | SHORT | INTEGER | LONG | BIG_INTEGER; |
| static final int MASK_KNOWN_NONINTEGERS = FLOAT | DOUBLE | BIG_DECIMAL; |
| static final int MASK_ALL_KNOWN_NUMERICALS = MASK_KNOWN_INTEGERS | MASK_KNOWN_NONINTEGERS; |
| static final int MASK_ALL_NUMERICALS = MASK_ALL_KNOWN_NUMERICALS | UNKNOWN_NUMERICAL_TYPE; |
| |
| static int classToTypeFlags(Class pClass) { |
| // We start with the most frequent cases |
| if (pClass == Object.class) { |
| return ACCEPTS_ANY_OBJECT; |
| } else if (pClass == String.class) { |
| return ACCEPTS_STRING; |
| } else if (pClass.isPrimitive()) { |
| if (pClass == Integer.TYPE) return INTEGER | ACCEPTS_NUMBER; |
| else if (pClass == Long.TYPE) return LONG | ACCEPTS_NUMBER; |
| else if (pClass == Double.TYPE) return DOUBLE | ACCEPTS_NUMBER; |
| else if (pClass == Float.TYPE) return FLOAT | ACCEPTS_NUMBER; |
| else if (pClass == Byte.TYPE) return BYTE | ACCEPTS_NUMBER; |
| else if (pClass == Short.TYPE) return SHORT | ACCEPTS_NUMBER; |
| else if (pClass == Character.TYPE) return CHARACTER; |
| else if (pClass == Boolean.TYPE) return ACCEPTS_BOOLEAN; |
| else return 0; |
| } else if (Number.class.isAssignableFrom(pClass)) { |
| if (pClass == Integer.class) return INTEGER | ACCEPTS_NUMBER; |
| else if (pClass == Long.class) return LONG | ACCEPTS_NUMBER; |
| else if (pClass == Double.class) return DOUBLE | ACCEPTS_NUMBER; |
| else if (pClass == Float.class) return FLOAT | ACCEPTS_NUMBER; |
| else if (pClass == Byte.class) return BYTE | ACCEPTS_NUMBER; |
| else if (pClass == Short.class) return SHORT | ACCEPTS_NUMBER; |
| else if (BigDecimal.class.isAssignableFrom(pClass)) return BIG_DECIMAL | ACCEPTS_NUMBER; |
| else if (BigInteger.class.isAssignableFrom(pClass)) return BIG_INTEGER | ACCEPTS_NUMBER; |
| else return UNKNOWN_NUMERICAL_TYPE | ACCEPTS_NUMBER; |
| } else if (pClass.isArray()) { |
| return ACCEPTS_ARRAY; |
| } else { |
| int flags = 0; |
| if (pClass.isAssignableFrom(String.class)) { |
| flags |= ACCEPTS_STRING; |
| } |
| if (pClass.isAssignableFrom(Date.class)) { |
| flags |= ACCEPTS_DATE; |
| } |
| if (pClass.isAssignableFrom(Boolean.class)) { |
| flags |= ACCEPTS_BOOLEAN; |
| } |
| if (pClass.isAssignableFrom(Map.class)) { |
| flags |= ACCEPTS_MAP; |
| } |
| if (pClass.isAssignableFrom(List.class)) { |
| flags |= ACCEPTS_LIST; |
| } |
| if (pClass.isAssignableFrom(Set.class)) { |
| flags |= ACCEPTS_SET; |
| } |
| |
| if (pClass == Character.class) { |
| flags |= CHARACTER; |
| } |
| |
| return flags; |
| } |
| } |
| |
| } |