All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.parser.AbstractParser Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

There is a newer version: 5.2.4
Show newest version
/*
 * Copyright (C) 2015 HaiYang Li
 *
 * Licensed 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 com.landawn.abacus.parser;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Function;

import com.landawn.abacus.exception.ParseException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.type.Type;
import com.landawn.abacus.type.TypeFactory;
import com.landawn.abacus.util.BiMap;
import com.landawn.abacus.util.ImmutableBiMap;
import com.landawn.abacus.util.ImmutableCollection;
import com.landawn.abacus.util.ImmutableList;
import com.landawn.abacus.util.ImmutableMap;
import com.landawn.abacus.util.ImmutableNavigableMap;
import com.landawn.abacus.util.ImmutableNavigableSet;
import com.landawn.abacus.util.ImmutableSet;
import com.landawn.abacus.util.ImmutableSortedMap;
import com.landawn.abacus.util.ImmutableSortedSet;
import com.landawn.abacus.util.N;
import com.landawn.abacus.util.Tuple;
import com.landawn.abacus.util.Tuple.Tuple2;

/**
 *
 * @author Haiyang Li
 * @param 
 * @param 
 * @since 0.8
 */
abstract class AbstractParser, DC extends DeserializationConfig> implements Parser {

    private static final Logger logger = LoggerFactory.getLogger(AbstractParser.class);

    static final String ELEMENT_SEPARATOR = ", ".intern();

    static final char[] ELEMENT_SEPARATOR_CHAR_ARRAY = ELEMENT_SEPARATOR.toCharArray();

    static final String NULL_STRING = "null".intern();

    static final char[] NULL_CHAR_ARRAY = NULL_STRING.toCharArray();

    static final String TRUE = Boolean.TRUE.toString().intern();

    static final char[] TRUE_CHAR_ARRAY = TRUE.toCharArray();

    static final String FALSE = Boolean.FALSE.toString().intern();

    static final char[] FALSE_CHAR_ARRAY = FALSE.toCharArray();

    // ... it has to be big enough to make it's safety to add element to
    // ArrayBlockingQueue.
    static final int POOL_SIZE = 1000;

    static final int CLS_POOL_SIZE = 3000;

    static final Type objType = TypeFactory.getType(Object.class);

    static final Type strType = TypeFactory.getType(String.class);

    static final Type boolType = TypeFactory.getType(Boolean.class);

    static final Type> propsMapType = TypeFactory.getType("Map");

    /**
     *
     * @param obj
     * @return
     */
    @Override
    public String serialize(Object obj) {
        return serialize(obj, null);
    }

    /**
     *
     * @param file
     * @param obj
     */
    @Override
    public void serialize(File file, Object obj) {
        serialize(file, obj, null);
    }

    /**
     *
     * @param os
     * @param obj
     */
    @Override
    public void serialize(OutputStream os, Object obj) {
        serialize(os, obj, null);
    }

    /**
     *
     * @param writer
     * @param obj
     */
    @Override
    public void serialize(Writer writer, Object obj) {
        serialize(writer, obj, null);
    }

    /**
     *
     * @param 
     * @param targetClass
     * @param st
     * @return
     */
    @Override
    public  T deserialize(Class targetClass, String st) {
        return deserialize(targetClass, st, null);
    }

    /**
     *
     * @param 
     * @param targetClass
     * @param file
     * @return
     */
    @Override
    public  T deserialize(Class targetClass, File file) {
        return deserialize(targetClass, file, null);
    }

    /**
     *
     * @param 
     * @param targetClass
     * @param is
     * @return
     */
    @Override
    public  T deserialize(Class targetClass, InputStream is) {
        return deserialize(targetClass, is, null);
    }

    /**
     *
     * @param 
     * @param targetClass
     * @param reader
     * @return
     */
    @Override
    public  T deserialize(Class targetClass, Reader reader) {
        return deserialize(targetClass, reader, null);
    }

    static final Map, Tuple2, Object>, Function>> mapOfCreatorAndConvertorForTargetType = new HashMap<>();

    static {
        mapOfCreatorAndConvertorForTargetType.put(ImmutableList.class,
                Tuple., Object>, Function> of(t -> new ArrayList<>(), new Function() {
                    @SuppressWarnings({ "rawtypes", "deprecation" })
                    @Override
                    public Object apply(Object t) {
                        return ImmutableList.wrap((List) t);
                    }
                }));

        mapOfCreatorAndConvertorForTargetType.put(ImmutableSet.class,
                Tuple., Object>, Function> of(t -> new HashSet<>(), new Function() {
                    @SuppressWarnings({ "rawtypes", "deprecation" })
                    @Override
                    public Object apply(Object t) {
                        return ImmutableSet.wrap((Set) t);
                    }
                }));

        mapOfCreatorAndConvertorForTargetType.put(ImmutableSortedSet.class,
                Tuple., Object>, Function> of(t -> new TreeSet<>(), new Function() {
                    @SuppressWarnings({ "rawtypes", "deprecation" })
                    @Override
                    public Object apply(Object t) {
                        return ImmutableSortedSet.wrap((SortedSet) t);
                    }
                }));

        mapOfCreatorAndConvertorForTargetType.put(ImmutableNavigableSet.class,
                Tuple., Object>, Function> of(t -> new TreeSet<>(), new Function() {
                    @SuppressWarnings({ "rawtypes", "deprecation" })
                    @Override
                    public Object apply(Object t) {
                        return ImmutableNavigableSet.wrap((NavigableSet) t);
                    }
                }));

        mapOfCreatorAndConvertorForTargetType.put(ImmutableCollection.class, mapOfCreatorAndConvertorForTargetType.get(ImmutableList.class));

        mapOfCreatorAndConvertorForTargetType.put(ImmutableMap.class,
                Tuple., Object>, Function> of(t -> new HashMap<>(), new Function() {
                    @SuppressWarnings({ "rawtypes", "deprecation" })
                    @Override
                    public Object apply(Object t) {
                        return ImmutableMap.wrap((Map) t);
                    }
                }));

        mapOfCreatorAndConvertorForTargetType.put(ImmutableBiMap.class,
                Tuple., Object>, Function> of(t -> new BiMap<>(), new Function() {
                    @SuppressWarnings({ "rawtypes", "deprecation" })
                    @Override
                    public Object apply(Object t) {
                        return ImmutableBiMap.wrap((BiMap) t);
                    }
                }));

        mapOfCreatorAndConvertorForTargetType.put(ImmutableSortedMap.class,
                Tuple., Object>, Function> of(t -> new TreeMap<>(), new Function() {
                    @SuppressWarnings({ "rawtypes", "deprecation" })
                    @Override
                    public Object apply(Object t) {
                        return ImmutableSortedMap.wrap((SortedMap) t);
                    }
                }));

        mapOfCreatorAndConvertorForTargetType.put(ImmutableNavigableMap.class,
                Tuple., Object>, Function> of(t -> new TreeMap<>(), new Function() {
                    @SuppressWarnings({ "rawtypes", "deprecation" })
                    @Override
                    public Object apply(Object t) {
                        return ImmutableNavigableMap.wrap((NavigableMap) t);
                    }
                }));

        mapOfCreatorAndConvertorForTargetType.put(Object.class, Tuple., Object>, Function> of(N::newInstance, t -> t));
    }

    protected static Class choosePropClass(Class propClass, Class attribeTypeClass) {
        if ((attribeTypeClass != null) && ((propClass == null) || propClass.isAssignableFrom(attribeTypeClass))) {
            return attribeTypeClass;
        }

        return propClass;
    }

    protected static Tuple2, Object>, Function> getCreatorAndConvertorForTargetType(Class propClass,
            Class attribeTypeClass) {
        final Class t = choosePropClass(propClass, attribeTypeClass);

        Tuple2, Object>, Function> result = mapOfCreatorAndConvertorForTargetType.get(t);

        if (result == null) {
            result = mapOfCreatorAndConvertorForTargetType.get(Object.class);
        }

        return result;
    }

    /**
     * New prop instance.
     *
     * @param 
     * @param propClass
     * @param attribeTypeClass
     * @return
     */
    @SuppressWarnings("unchecked")
    protected static  T newPropInstance(Class propClass, Class attribeTypeClass) {
        if ((attribeTypeClass != null) && ((propClass == null) || propClass.isAssignableFrom(attribeTypeClass))) {
            try {
                return (T) N.newInstance(attribeTypeClass);
            } catch (Exception e) {
                if (logger.isInfoEnabled()) {
                    logger.info("Failed to new instance by type attribute: " + attribeTypeClass.getCanonicalName());
                }
            }
        }

        if (propClass != null) {
            return (T) N.newInstance(propClass);
        }

        throw new ParseException("Failed to create property instance with property class: " + propClass + " and attribute " + attribeTypeClass);
    }

    /**
     * Gets the concrete class.
     *
     * @param targetClass
     * @param typeClass
     * @return
     */
    protected static Class getConcreteClass(Class targetClass, Class typeClass) {
        if (typeClass == null) {
            return targetClass;
        } else if (targetClass == null) {
            return typeClass;
        } else if (targetClass == typeClass || targetClass.isAssignableFrom(typeClass)) {
            return typeClass;
        } else {
            return targetClass;
        }
    }

    /**
     * Collection 2 array.
     *
     * @param 
     * @param targetClass
     * @param c
     * @return
     */
    protected static  T collection2Array(Class targetClass, final Collection c) {
        if (c == null) {
            return null;
        }

        final Type targetType = N.typeOf(targetClass);

        if (targetType.isPrimitiveArray()) {
            // continue
        } else {
            // looking for the right array class.
            for (Object e : c) {
                if (e != null) {
                    if (targetClass.getComponentType().isAssignableFrom(e.getClass())) {
                        return (T) targetType.collection2Array(c);
                    } else {
                        return (T) c.toArray((Object[]) N.newArray(e.getClass(), c.size()));
                    }
                }
            }
        }

        return (T) targetType.collection2Array(c);
    }

    protected static void createNewFileIfNotExists(final File file) throws IOException {
        if (!file.exists() && file.createNewFile() == false) {
            throw new IOException("Failed to create new file: " + file.getName());
        }
    }
}