    001/*-
    002 * Copyright (c) 2019 Diamond Light Source Ltd.
    003 *
    004 * All rights reserved. This program and the accompanying materials
    005 * are made available under the terms of the Eclipse Public License v1.0
    006 * which accompanies this distribution, and is available at
    007 * http://www.eclipse.org/legal/epl-v10.html
    008 */
    009
    010package org.eclipse.january.dataset;
    011
    012import java.lang.reflect.Array;
    013import java.util.Date;
    014import java.util.HashMap;
    015import java.util.LinkedHashMap;
    016import java.util.List;
    017import java.util.Map;
    018import java.util.Map.Entry;
    019import java.util.Set;
    020
    021import org.apache.commons.math3.complex.Complex;
    022
    023/**
    024 * @since 2.3
    025 */
    026public class InterfaceUtils {
    027        private static final Map<Class<?>, Class<? extends Dataset>> class2Interface;
    028
    029        private static final Map<Class<? extends Dataset>, Class<?>> interface2Class;
    030
    031        private static final Map<Class<?>, Integer> elementBytes;
    032
    033        private static final Map<Class<?>, Class<?>> bestFloatElement;
    034
    035        private static final Map<Class<? extends Dataset>, Class<? extends CompoundDataset>> interface2Compound;
    036
    037        private static final Map<Class<? extends CompoundDataset>, Class<? extends Dataset>> compound2Interface;
    038
    039        private static Set<Class<? extends Dataset>> interfaces;
    040
    041        static {
    042                class2Interface = createClassInterfaceMap();
    043
    044                interface2Class = createInterfaceClassMap();
    045                interfaces = interface2Class.keySet();
    046
    047                elementBytes = createElementBytesMap();
    048
    049                bestFloatElement = createBestFloatElementMap();
    050
    051                interface2Compound = createInterfaceCompoundMap();
    052                compound2Interface = new HashMap<Class<? extends CompoundDataset>, Class<? extends Dataset>>();
    053                for (Entry<Class<? extends Dataset>, Class<? extends CompoundDataset>> e : interface2Compound.entrySet()) {
    054                        compound2Interface.put(e.getValue(), e.getKey());
    055                }
    056                compound2Interface.put(RGBByteDataset.class, ByteDataset.class);
    057                compound2Interface.put(RGBDataset.class, ShortDataset.class);
    058                compound2Interface.put(ComplexFloatDataset.class, FloatDataset.class);
    059                compound2Interface.put(ComplexDoubleDataset.class, DoubleDataset.class);
    060        }
    061
    062        private static Map<Class<?>, Class<? extends Dataset>> createClassInterfaceMap() {
    063                Map<Class<?>, Class<? extends Dataset>> result = new HashMap<>();
    064                result.put(Boolean.class, BooleanDataset.class);
    065                result.put(Byte.class, ByteDataset.class);
    066                result.put(Short.class, ShortDataset.class);
    067                result.put(Integer.class, IntegerDataset.class);
    068                result.put(Long.class, LongDataset.class);
    069                result.put(Float.class, FloatDataset.class);
    070                result.put(Double.class, DoubleDataset.class);
    071                result.put(boolean.class, BooleanDataset.class);
    072                result.put(byte.class, ByteDataset.class);
    073                result.put(short.class, ShortDataset.class);
    074                result.put(int.class, IntegerDataset.class);
    075                result.put(long.class, LongDataset.class);
    076                result.put(float.class, FloatDataset.class);
    077                result.put(double.class, DoubleDataset.class);
    078                result.put(Complex.class, ComplexDoubleDataset.class);
    079                result.put(String.class, StringDataset.class);
    080                result.put(Date.class, DateDataset.class);
    081                return result;
    082        }
    083
    084        private static Map<Class<? extends Dataset>, Class<?>> createInterfaceClassMap() {
    085                Map<Class<? extends Dataset>, Class<?>> result = new LinkedHashMap<>();
    086                // ordering is likelihood of occurrence as it is used in an iterative check
    087                // XXX for current implementation
    088                result.put(DoubleDataset.class, Double.class);
    089                result.put(DateDataset.class, Date.class); // XXX must be before string (and integer for unit test)
    090                result.put(IntegerDataset.class, Integer.class);
    091                result.put(BooleanDataset.class, Boolean.class);
    092                result.put(StringDataset.class, String.class);
    093                result.put(ComplexDoubleDataset.class, Double.class); // XXX must be before compound double
    094                result.put(RGBByteDataset.class, Byte.class); // XXX must be before compound byte
    095                result.put(RGBDataset.class, Short.class); // XXX must be before compound short
    096                result.put(ByteDataset.class, Byte.class);
    097                result.put(ShortDataset.class, Short.class);
    098                result.put(LongDataset.class, Long.class);
    099                result.put(FloatDataset.class, Float.class);
    100                result.put(ComplexFloatDataset.class, Float.class); // XXX must be before compound float
    101                result.put(CompoundShortDataset.class, Short.class);
    102                result.put(CompoundByteDataset.class, Byte.class);
    103                result.put(CompoundIntegerDataset.class, Integer.class);
    104                result.put(CompoundLongDataset.class, Long.class);
    105                result.put(CompoundFloatDataset.class, Float.class);
    106                result.put(CompoundDoubleDataset.class, Double.class);
    107                result.put(ObjectDataset.class, Object.class);
    108                return result;
    109        }
    110
    111        private static Map<Class<?>, Integer> createElementBytesMap() {
    112                Map<Class<?>, Integer> result = new LinkedHashMap<>();
    113                result.put(Boolean.class, 1);
    114                result.put(Byte.class, Byte.SIZE / 8);
    115                result.put(Short.class, Short.SIZE / 8);
    116                result.put(Integer.class, Integer.SIZE / 8);
    117                result.put(Long.class, Long.SIZE / 8);
    118                result.put(Float.class, Float.SIZE / 8);
    119                result.put(Double.class, Double.SIZE / 8);
    120                result.put(String.class, 1);
    121                result.put(Object.class, 1);
    122                result.put(Date.class, 1);
    123                return result;
    124        }
    125
    126        private static Map<Class<?>, Class<?>> createBestFloatElementMap() {
    127                Map<Class<?>, Class<?>> result = new HashMap<>();
    128                result.put(Boolean.class, Float.class);
    129                result.put(Byte.class, Float.class);
    130                result.put(Short.class, Float.class);
    131                result.put(Integer.class, Double.class);
    132                result.put(Long.class, Double.class);
    133                result.put(Float.class, Float.class);
    134                result.put(Double.class, Double.class);
    135                return result;
    136        }
    137
    138        private static Map<Class<? extends Dataset>, Class<? extends CompoundDataset>> createInterfaceCompoundMap() {
    139                Map<Class<? extends Dataset>, Class<? extends CompoundDataset>> result = new HashMap<>();
    140                result.put(ByteDataset.class, CompoundByteDataset.class);
    141                result.put(ShortDataset.class, CompoundShortDataset.class);
    142                result.put(IntegerDataset.class, CompoundIntegerDataset.class);
    143                result.put(LongDataset.class, CompoundLongDataset.class);
    144                result.put(FloatDataset.class, CompoundFloatDataset.class);
    145                result.put(DoubleDataset.class, CompoundDoubleDataset.class);
    146                return result;
    147        }
    148
    149        /**
    150         * @param object input
    151         * @param dInterface dataset interface
    152         * @return true if object is an instance of dataset interface
    153         */
    154        public static boolean isInstance(Object object, final Class<? extends Dataset> dInterface) {
    155                return dInterface.isInstance(object);
    156        }
    157
    158        /**
    159         * @param clazz dataset class
    160         * @param dInterface dataset interface
    161         * @return true if given class implements interface
    162         */
    163        public static boolean hasInterface(final Class<? extends Dataset> clazz, final Class<? extends Dataset> dInterface) {
    164                return dInterface.isAssignableFrom(clazz);
    165        }
    166
    167        /**
    168         * @param clazz dataset class
    169         * @param dInterfaces dataset interface
    170         * @return true if given class implements any of the interfaces
    171         */
    172        @SuppressWarnings("unchecked")
    173        public static boolean hasInterface(final Class<? extends Dataset> clazz, final Class<? extends Dataset>... dInterfaces) {
    174                for (Class<? extends Dataset> d : dInterfaces) {
    175                        if (d != null && d.isAssignableFrom(clazz)) {
    176                                return true;
    177                        }
    178                }
    179                return false;
    180        }
    181
    182        /**
    183         * @param clazz element class
    184         * @return true if supported as an element class (note, Object is not supported)
    185         */
    186        public static boolean isElementSupported(Class<? extends Object> clazz) {
    187                return class2Interface.containsKey(clazz);
    188        }
    189
    190        /**
    191         * @param clazz dataset class
    192         * @return (boxed) class of constituent element
    193         */
    194        public static Class<?> getElementClass(final Class<? extends Dataset> clazz) {
    195                Class<? extends Dataset> eInterface = getElementalInterface(clazz);
    196                return interface2Class.get(eInterface);
    197        }
    198
    199        /**
    200         * Get dataset interface from an object. The following are supported: Java Number objects, Apache common math Complex
    201         * objects, Java arrays and lists, Dataset objects and ILazyDataset object
    202         *
    203         * @param obj input
    204         * @return dataset interface
    205         */
    206        public static Class <? extends Dataset> getInterface(Object obj) {
    207                Class<? extends Dataset> dc = null;
    208
    209                if (obj == null) {
    210                        return ObjectDataset.class;
    211                }
    212
    213                if (obj instanceof List<?>) {
    214                        List<?> jl = (List<?>) obj;
    215                        int l = jl.size();
    216                        for (int i = 0; i < l; i++) {
    217                                dc = getBestInterface(dc, getInterface(jl.get(i)));
    218                        }
    219                } else if (obj.getClass().isArray()) {
    220                        Class<?> ca = obj.getClass().getComponentType();
    221                        if (isElementSupported(ca)) {
    222                                return class2Interface.get(ca);
    223                        }
    224                        int l = Array.getLength(obj);
    225                        for (int i = 0; i < l; i++) {
    226                                Object lo = Array.get(obj, i);
    227                                dc = getBestInterface(dc, getInterface(lo));
    228                        }
    229                } else if (obj instanceof Dataset) {
    230                        dc = findSubInterface(((Dataset) obj).getClass());
    231                } else if (obj instanceof ILazyDataset) {
    232                        dc = getInterfaceFromClass(((ILazyDataset) obj).getElementsPerItem(), ((ILazyDataset) obj).getElementClass());
    233                } else {
    234                        Class<?> ca = obj.getClass();
    235                        if (isElementSupported(ca)) {
    236                                return class2Interface.get(ca);
    237                        }
    238                }
    239                return dc;
    240        }
    241
    242        /**
    243         * Find sub-interface of Dataset
    244         * @param clazz dataset class
    245         * @return sub-interface or null if given class is Dataset.class
    246         * @since 2.3
    247         */
    248        public static Class<? extends Dataset> findSubInterface(Class<? extends Dataset> clazz) {
    249                if (Dataset.class.equals(clazz)) {
    250                        throw new IllegalArgumentException("Class must be a sub-interface of Dataset");
    251                }
    252                for (Class<? extends Dataset> i : interfaces) {
    253                        if (i.isAssignableFrom(clazz)) {
    254                                return i;
    255                        }
    256                }
    257                // XXX special cases for current implementation
    258                if (BooleanDatasetBase.class.equals(clazz)) {
    259                        return BooleanDataset.class;
    260                }
    261                if (StringDatasetBase.class.equals(clazz)) {
    262                        return StringDataset.class;
    263                }
    264                if (ObjectDatasetBase.class.equals(clazz)) {
    265                        return ObjectDataset.class;
    266                }
    267                throw new IllegalArgumentException("Unknown sub-interface of Dataset");
    268        }
    269
    270        /**
    271         * @param elementsPerItem item size
    272         * @param elementClass element class
    273         * @return dataset interface
    274         */
    275        public static Class<? extends Dataset> getInterfaceFromClass(int elementsPerItem, Class<?> elementClass) {
    276                Class<? extends Dataset> clazz = class2Interface.get(elementClass);
    277                if (clazz == null) {
    278                        throw new IllegalArgumentException("Class of object not supported");
    279                }
    280                if (elementsPerItem > 1 && interface2Compound.containsKey(clazz)) {
    281                        clazz = interface2Compound.get(clazz);
    282                }
    283                return clazz;
    284        }
    285
    286        /**
    287         * @param clazz dataset interface
    288         * @return elemental dataset interface available for given dataset interface
    289         */
    290        public static Class<? extends Dataset> getElementalInterface(final Class<? extends Dataset> clazz) {
    291                Class<? extends Dataset> c = findSubInterface(clazz);
    292                return isElemental(c) ? c : compound2Interface.get(c);
    293        }
    294
    295        /**
    296         * @param clazz dataset interface
    297         * @return compound dataset interface available for given dataset interface
    298         */
    299        @SuppressWarnings("unchecked")
    300        public static Class<? extends CompoundDataset> getCompoundInterface(final Class<? extends Dataset> clazz) {
    301                Class<? extends CompoundDataset> c = null;
    302                Class<? extends Dataset> d = findSubInterface(clazz);
    303                if (isElemental(d)) {
    304                        c = interface2Compound.get(d);
    305                } else {
    306                        c = (Class<? extends CompoundDataset>) d;
    307                }
    308                if (c == null) {
    309                        throw new IllegalArgumentException("Interface cannot be compound");
    310                }
    311                return c;
    312        }
    313
    314        /**
    315         * @param a dataset
    316         * @return true if dataset is not compound or complex
    317         */
    318        public static boolean isElemental(ILazyDataset a) {
    319                return isElemental(getInterface(a));
    320        }
    321
    322        /**
    323         * @param clazz dataset class
    324         * @return true if dataset interface is not compound or complex
    325         */
    326        public static boolean isElemental(Class<? extends Dataset> clazz) {
    327                return !CompoundDataset.class.isAssignableFrom(clazz);
    328        }
    329
    330        /**
    331         * @param clazz dataset class
    332         * @return true if dataset interface is compound (not complex)
    333         */
    334        public static boolean isCompound(Class<? extends Dataset> clazz) {
    335                Class<? extends Dataset> c = findSubInterface(clazz);
    336                return compound2Interface.containsKey(c);
    337        }
    338
    339        /**
    340         * @param a dataset
    341         * @return true if dataset has integer elements
    342         */
    343        public static boolean isInteger(ILazyDataset a) {
    344                return a instanceof Dataset ? isInteger(((Dataset) a).getClass()) : isElementClassInteger(a.getElementClass());
    345        }
    346
    347        /**
    348         * @param a dataset
    349         * @return true if dataset has floating point elements
    350         */
    351        public static boolean isFloating(ILazyDataset a) {
    352                return a instanceof Dataset ? isFloating(((Dataset) a).getClass()) : isElementClassFloating(a.getElementClass());
    353        }
    354
    355        /**
    356         * @param clazz dataset class
    357         * @return true if dataset interface has integer elements
    358         */
    359        public static boolean isInteger(Class<? extends Dataset> clazz) {
    360                Class<?> c = getElementClass(clazz);
    361                return isElementClassInteger(c);
    362        }
    363
    364        /**
    365         * @param clazz dataset class
    366         * @return true if dataset interface has floating point elements
    367         */
    368        public static boolean isFloating(Class<? extends Dataset> clazz) {
    369                Class<?> c = getElementClass(clazz);
    370                return isElementClassFloating(c);
    371        }
    372
    373        private static boolean isElementClassInteger(Class<?> c) {
    374                return Byte.class == c || Short.class == c || Integer.class == c || Long.class == c;
    375        }
    376
    377        private static boolean isElementClassFloating(Class<?> c) {
    378                return Double.class == c || Float.class == c;
    379        }
    380
    381        /**
    382         * @param clazz dataset class
    383         * @return true if dataset interface has complex items
    384         */
    385        public static boolean isComplex(Class<? extends Dataset> clazz) {
    386                return ComplexDoubleDataset.class.isAssignableFrom(clazz) || ComplexFloatDataset.class.isAssignableFrom(clazz);
    387        }
    388
    389        /**
    390         * @param clazz dataset class
    391         * @return true if dataset interface has numerical elements
    392         */
    393        public static boolean isNumerical(Class<? extends Dataset> clazz) {
    394                Class<?> c = getElementClass(clazz);
    395                return Boolean.class == c || isElementClassInteger(c) || isElementClassFloating(c);
    396        }
    397
    398        /**
    399         * @param clazz dataset class
    400         * @return number of elements per item
    401         */
    402        public static int getElementsPerItem(Class<? extends Dataset> clazz) {
    403                if (isComplex(clazz)) {
    404                        return 2;
    405                } else if (RGBByteDataset.class.isAssignableFrom(clazz) || RGBDataset.class.isAssignableFrom(clazz)) {
    406                        return 3;
    407                }
    408                if (CompoundDataset.class.isAssignableFrom(clazz)) {
    409                        throw new UnsupportedOperationException("Multi-element type unsupported");
    410                }
    411                return 1;
    412        }
    413
    414        /**
    415         * Find dataset interface that best fits given classes. The best class takes into account complex and array datasets
    416         *
    417         * @param a
    418         *            first dataset class
    419         * @param b
    420         *            second dataset class
    421         * @return best dataset interface
    422         */
    423        public static Class<? extends Dataset> getBestInterface(Class<? extends Dataset> a, Class<? extends Dataset> b) {
    424                if (a == null) {
    425                        return b;
    426                }
    427                if (b == null) {
    428                        return a;
    429                }
    430
    431                boolean isElemental = true;
    432                final boolean az = isComplex(a);
    433                if (!az && !isElemental(a)) {
    434                        isElemental = false;
    435                        a = compound2Interface.get(a);
    436                }
    437                final boolean bz = isComplex(b);
    438                if (!bz && !isElemental(b)) {
    439                        isElemental = false;
    440                        b = compound2Interface.get(b);
    441                }
    442
    443                if (isFloating(a)) {
    444                        if (!isFloating(b)) {
    445                                b = getBestFloatInterface(b); // note doesn't change if not numerical!!!
    446                        }
    447                        if (az) {
    448                                b = DoubleDataset.class.isAssignableFrom(b) ? ComplexDoubleDataset.class : ComplexFloatDataset.class;
    449                        }
    450                } else if (isFloating(b)) {
    451                        a = getBestFloatInterface(a);
    452                        if (bz) {
    453                                a = DoubleDataset.class.isAssignableFrom(a) ? ComplexDoubleDataset.class : ComplexFloatDataset.class;
    454                        }
    455                }
    456
    457                Class<? extends Dataset> c = isBetter(interface2Class.get(a), interface2Class.get(b)) ? a : b;
    458                if ((az || bz) && !isComplex(c)) {
    459                        c = DoubleDataset.class.isAssignableFrom(c) ? ComplexDoubleDataset.class : ComplexFloatDataset.class;
    460                }
    461
    462                if (!isElemental && interface2Compound.containsKey(c)) {
    463                        c = interface2Compound.get(c);
    464                }
    465                return c;
    466        }
    467
    468        private static boolean isBetter(Class<?> a, Class<?> b) {
    469                for (Class<?> k : elementBytes.keySet()) { // elements order in increasing width (for numerical primitives)
    470                        if (k.equals(b)) {
    471                                return true;
    472                        }
    473                        if (k.equals(a)) {
    474                                return false;
    475                        }
    476                }
    477                return true;
    478        }
    479
    480        /**
    481         * The largest dataset type suitable for a summation of around a few thousand items without changing from the "kind"
    482         * of dataset
    483         *
    484         * @param a dataset
    485         * @return largest dataset type available for given dataset type
    486         */
    487        public static Class<? extends Dataset> getLargestInterface(Dataset a) {
    488                if (a instanceof BooleanDataset || a instanceof ByteDataset || a instanceof ShortDataset) {
    489                        return IntegerDataset.class;
    490                } else if (a instanceof IntegerDataset) {
    491                        return LongDataset.class;
    492                } else if (a instanceof FloatDataset) {
    493                        return DoubleDataset.class;
    494                } else if (a instanceof ComplexFloatDataset) {
    495                        return ComplexDoubleDataset.class;
    496                } else if (a instanceof CompoundByteDataset || a instanceof CompoundShortDataset) {
    497                        return CompoundIntegerDataset.class;
    498                } else if (a instanceof CompoundIntegerDataset) {
    499                        return CompoundLongDataset.class;
    500                } else if (a instanceof CompoundFloatDataset) {
    501                        return CompoundDoubleDataset.class;
    502                }
    503                return a.getClass();
    504        }
    505
    506        /**
    507         * Find floating point dataset interface that best fits given class. The best interface takes into account complex and array
    508         * datasets
    509         *
    510         * @param clazz dataset class
    511         * @return best dataset interface
    512         */
    513        public static Class<? extends Dataset> getBestFloatInterface(Class<? extends Dataset> clazz) {
    514                Class<?> e = interface2Class.get(clazz);
    515                if (bestFloatElement.containsKey(e)) {
    516                        e = bestFloatElement.get(e);
    517                        return class2Interface.get(e);
    518                }
    519                return clazz;
    520        }
    521
    522        /**
    523         * @param isize
    524         *            number of elements in an item
    525         * @param clazz dataset interface
    526         * @return length of single item in bytes
    527         */
    528        public static int getItemBytes(final int isize, Class<? extends Dataset> clazz) {
    529                Class<?> eClass = interface2Class.get(clazz);
    530                if (eClass == null) {
    531                        eClass = interface2Class.get(findSubInterface(clazz));
    532                }
    533                int bytes = elementBytes.get(eClass);
    534
    535                return isize * bytes;
    536        }
    537
    538        /**
    539         * Convert double array to primitive array
    540         * @param clazz dataset interface
    541         * @param x values
    542         * @return biggest native primitive array if integer. Return null if not interface is not numerical
    543         */
    544        public static Object fromDoublesToBiggestPrimitives(Class<? extends Dataset> clazz, double[] x) {
    545                if (BooleanDataset.class.isAssignableFrom(clazz) || ByteDataset.class.isAssignableFrom(clazz)
    546                                || ShortDataset.class.isAssignableFrom(clazz) || IntegerDataset.class.isAssignableFrom(clazz)) {
    547                        int[] i32 = new int[x.length];
    548                        for (int i = 0; i < x.length; i++) {
    549                                i32[i] = (int) (long) x[i];
    550                        }
    551                        return i32;
    552                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    553                        long[] i64 = new long[x.length];
    554                        for (int i = 0; i < x.length; i++) {
    555                                i64[i] = (long) x[i];
    556                        }
    557                        return i64;
    558                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    559                        float[] f32 = new float[x.length];
    560                        for (int i = 0; i < x.length; i++) {
    561                                f32[i] = (float) x[i];
    562                        }
    563                        return f32;
    564                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    565                        return x;
    566                }
    567                return null;
    568        }
    569
    570        /**
    571         * Convert double to number
    572         * @param clazz dataset interface
    573         * @param x value
    574         * @return number if integer. Return null if not interface is not numerical
    575         * @since 2.3
    576         */
    577        public static Number fromDoubleToNumber(Class<? extends Dataset> clazz, double x) {
    578                if (BooleanDataset.class.isAssignableFrom(clazz) || ByteDataset.class.isAssignableFrom(clazz)) {
    579                        return Byte.valueOf((byte) (long) x);
    580                } else if (ShortDataset.class.isAssignableFrom(clazz)) {
    581                        return Short.valueOf((short) (long) x);
    582                } else if (IntegerDataset.class.isAssignableFrom(clazz)) {
    583                        return Integer.valueOf((int) (long) x);
    584                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    585                        return Long.valueOf((long) x);
    586                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    587                        return Float.valueOf((float) x);
    588                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    589                        return Double.valueOf(x);
    590                }
    591                return null;
    592        }
    593
    594        /**
    595         * Convert double to number
    596         * @param clazz dataset interface
    597         * @param x value
    598         * @return biggest number if integer. Return null if not interface is not numerical
    599         */
    600        public static Number fromDoubleToBiggestNumber(Class<? extends Dataset> clazz, double x) {
    601                if (BooleanDataset.class.isAssignableFrom(clazz) || ByteDataset.class.isAssignableFrom(clazz)
    602                                || ShortDataset.class.isAssignableFrom(clazz) || IntegerDataset.class.isAssignableFrom(clazz)) {
    603                        return Integer.valueOf((int) (long) x);
    604                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    605                        return Long.valueOf((long) x);
    606                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    607                        return Float.valueOf((float) x);
    608                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    609                        return Double.valueOf(x);
    610                }
    611                return null;
    612        }
    613
    614        /**
    615         * @param clazz dataset interface
    616         * @param x value
    617         * @return biggest native primitive if integer
    618         * @since 2.3
    619         */
    620        public static Number toBiggestNumber(Class<? extends Dataset> clazz, Number x) {
    621                if (BooleanDataset.class.isAssignableFrom(clazz) || ByteDataset.class.isAssignableFrom(clazz)
    622                                || ShortDataset.class.isAssignableFrom(clazz) || IntegerDataset.class.isAssignableFrom(clazz)) {
    623                        return x instanceof Integer ? x : Integer.valueOf(x.intValue());
    624                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    625                        return x instanceof Long ? x : Long.valueOf(x.longValue());
    626                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    627                        return x instanceof Float ? x : Float.valueOf(x.floatValue());
    628                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    629                        return x instanceof Double ? x : Double.valueOf(x.doubleValue());
    630                }
    631                return null;
    632        }
    633}