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

com.landawn.abacus.type.AbstractType 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.type;

import java.io.IOException;
import java.io.Writer;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.landawn.abacus.parser.SerializationConfig;
import com.landawn.abacus.util.CharacterWriter;
import com.landawn.abacus.util.ClassUtil;
import com.landawn.abacus.util.N;
import com.landawn.abacus.util.Numbers;
import com.landawn.abacus.util.TypeAttrParser;

/**
 *
 * @author Haiyang Li
 * @param 
 * @since 0.8
 */
public abstract class AbstractType implements Type {

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

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

    static final String SYS_TIME = "sysTime";

    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();

    @SuppressWarnings("rawtypes")
    protected static final Type[] EMPTY_TYPE_ARRAY = {};

    private static final Map separatorConvertor = new HashMap<>();

    static {
        separatorConvertor.put(".", "\\.");
        separatorConvertor.put("|", "\\|");
        separatorConvertor.put("-", "\\-");
        separatorConvertor.put("*", "\\*");
        separatorConvertor.put("?", "\\?");
        separatorConvertor.put("+", "\\+");
        separatorConvertor.put("$", "\\$");
        separatorConvertor.put("^", "\\^");
        separatorConvertor.put("\\", "\\\\");
    }

    private final String name;

    private final String xmlName;

    protected AbstractType(String typeName) {
        String simpleName = typeName;

        if (typeName.indexOf('.') > 0) { //NOSONAR
            // generic type.

            int index = typeName.indexOf('<');
            String tmpTypeName = index > 0 ? typeName.substring(0, index) : typeName;

            try {
                Class cls = ClassUtil.forClass(tmpTypeName);
                if (cls != null) {
                    cls = ClassUtil.forClass(ClassUtil.getSimpleClassName(cls));
                    if (cls != null) {
                        simpleName = ClassUtil.getSimpleClassName(cls) + (index > 0 ? typeName.substring(index) : N.EMPTY_STRING);
                    }
                }
            } catch (Exception e) {
                // ignore;
            }
        }

        name = simpleName;
        xmlName = name.replaceAll("<", "<").replaceAll(">", ">"); //NOSONAR
    }

    protected static String[] getTypeParameters(String typeName) {
        return TypeAttrParser.parse(typeName).getTypeParameters();
    }

    protected static String[] getParameters(String typeName) {
        return TypeAttrParser.parse(typeName).getParameters();
    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public String name() {
        return name;
    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public String declaringName() {
        //        final String name = getName();
        //        final int index = name.lastIndexOf('.');
        //
        //        if (index >= 0) {
        //            final int index2 = name.lastIndexOf('<');
        //
        //            if (index2 < 0 || index2 > index) {
        //                return name.substring(index + 1);
        //            }
        //        }
        //
        //        return name;

        return name;
    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public String xmlName() {
        return xmlName;
    }

    /**
     * Checks if is primitive type.
     *
     * @return true, if is primitive type
     */
    @Override
    public boolean isPrimitiveType() {
        return false;
    }

    /**
     * Checks if is primitive wrapper.
     *
     * @return true, if is primitive wrapper
     */
    @Override
    public boolean isPrimitiveWrapper() {
        return false;
    }

    /**
     * Checks if is primitive list.
     *
     * @return true, if is primitive list
     */
    @Override
    public boolean isPrimitiveList() {
        return false;
    }

    /**
     * Checks if is boolean.
     *
     * @return true, if is boolean
     */
    @Override
    public boolean isBoolean() {
        return false;
    }

    /**
     * Checks if is number.
     *
     * @return true, if is number
     */
    @Override
    public boolean isNumber() {
        return false;
    }

    /**
     * Checks if is string.
     *
     * @return true, if is string
     */
    @Override
    public boolean isString() {
        return false;
    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public boolean isCharSequence() {
        return false;
    }

    /**
     * Checks if is date.
     *
     * @return true, if is date
     */
    @Override
    public boolean isDate() {
        return false;
    }

    /**
     * Checks if is calendar.
     *
     * @return true, if is calendar
     */
    @Override
    public boolean isCalendar() {
        return false;
    }

    /**
     * Checks if is joda date time.
     *
     * @return true, if is joda date time
     */
    @Override
    public boolean isJodaDateTime() {
        return false;
    }

    /**
     * Checks if is primitive array.
     *
     * @return true, if is primitive array
     */
    @Override
    public boolean isPrimitiveArray() {
        return false;
    }

    /**
     * Checks if is primitive byte array.
     *
     * @return true, if is primitive byte array
     */
    @Override
    public boolean isPrimitiveByteArray() {
        return false;
    }

    /**
     * Checks if is object array.
     *
     * @return true, if is object array
     */
    @Override
    public boolean isObjectArray() {
        return false;
    }

    /**
     * Checks if is array.
     *
     * @return true, if is array
     */
    @Override
    public boolean isArray() {
        return false;
    }

    /**
     * Checks if is list.
     *
     * @return true, if is list
     */
    @Override
    public boolean isList() {
        return false;
    }

    /**
     * Checks if is sets the.
     *
     * @return true, if is sets the
     */
    @Override
    public boolean isSet() {
        return false;
    }

    /**
     * Checks if is collection.
     *
     * @return true, if is collection
     */
    @Override
    public boolean isCollection() {
        return false;
    }

    /**
     * Checks if is map.
     *
     * @return true, if is map
     */
    @Override
    public boolean isMap() {
        return false;
    }

    /**
     * Checks if is bean.
     *
     * @return true, if is bean
     */
    @Override
    public boolean isBean() {
        return false;
    }

    /**
     * Checks if is map bean.
     *
     * @return true, if is map bean
     */
    @Override
    public boolean isMapEntity() {
        return false;
    }

    /**
     * Checks if is bean id.
     *
     * @return true, if is bean id
     */
    @Override
    public boolean isEntityId() {
        return false;
    }

    /**
     * Checks if is data set.
     *
     * @return true, if is data set
     */
    @Override
    public boolean isDataSet() {
        return false;
    }

    /**
     * Checks if is input stream.
     *
     * @return true, if is input stream
     */
    @Override
    public boolean isInputStream() {
        return false;
    }

    /**
     * Checks if is reader.
     *
     * @return true, if is reader
     */
    @Override
    public boolean isReader() {
        return false;
    }

    /**
     * Checks if is byte buffer.
     *
     * @return true, if is byte buffer
     */
    @Override
    public boolean isByteBuffer() {
        return false;
    }

    /**
     * Checks if is generic type.
     *
     * @return true, if is generic type
     */
    @Override
    public boolean isGenericType() {
        return N.notNullOrEmpty(getParameterTypes());
    }

    /**
     * Checks if is immutable.
     *
     * @return true, if is immutable
     */
    @Override
    public boolean isImmutable() {
        return false;
    }

    /**
     * Checks if is comparable.
     *
     * @return true, if is comparable
     */
    @Override
    public boolean isComparable() {
        return false;
    }

    /**
     * Checks if is serializable.
     *
     * @return true, if is serializable
     */
    @Override
    public boolean isSerializable() {
        return true;
    }

    /**
     * Gets the serialization type.
     *
     * @return
     */
    @Override
    public SerializationType getSerializationType() {
        return isSerializable() ? SerializationType.SERIALIZABLE : SerializationType.UNKNOWN;
    }

    /**
     * Checks if is optional or nullable.
     *
     * @return true, if is optional or nullable
     */
    @Override
    public boolean isOptionalOrNullable() {
        return false;
    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public boolean isObjectType() {
        return false;
    }

    /**
     * Gets the element type.
     *
     * @return
     */
    @Override
    public Type getElementType() {
        return null;
    }

    /**
     * Gets the parameter types.
     *
     * @return
     */
    @Override
    public Type[] getParameterTypes() {
        return AbstractType.EMPTY_TYPE_ARRAY;
    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public T defaultValue() {
        return null;
    }

    /**
     * 
     *
     * @param value 
     * @return 
     */
    @Override
    public boolean isDefaultValue(final T value) {
        return N.equals(defaultValue(), value);
    }

    /**
     *
     * @param x
     * @param y
     * @return
     */
    @SuppressWarnings("unchecked")
    @Override
    public int compare(T x, T y) {
        if (isComparable()) {
            return (x == null) ? ((y == null) ? 0 : (-1)) : ((y == null) ? 1 : ((Comparable) x).compareTo(y));
        } else {
            throw new UnsupportedOperationException(name() + " doesn't support compare Operation");
        }
    }

    /**
     *
     * @param obj
     * @return
     */
    @Override
    public T valueOf(final Object obj) {
        return valueOf(obj == null ? null : N.typeOf(obj.getClass()).stringOf(obj));
    }

    /**
     *
     * @param cbuf
     * @param offset
     * @param len
     * @return
     */
    @Override
    public T valueOf(char[] cbuf, int offset, int len) {
        return valueOf(cbuf == null ? null : String.valueOf(cbuf, offset, len));
    }

    /**
     *
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException the SQL exception
     */
    @Override
    public T get(ResultSet rs, int columnIndex) throws SQLException {
        return valueOf(rs.getString(columnIndex));
    }

    /**
     *
     * @param rs
     * @param columnLabel
     * @return
     * @throws SQLException the SQL exception
     */
    @Override
    public T get(ResultSet rs, String columnLabel) throws SQLException {
        return valueOf(rs.getString(columnLabel));
    }

    /**
     *
     * @param stmt
     * @param columnIndex
     * @param x
     * @throws SQLException the SQL exception
     */
    @Override
    public void set(PreparedStatement stmt, int columnIndex, T x) throws SQLException {
        stmt.setString(columnIndex, stringOf(x));
    }

    /**
     *
     * @param stmt
     * @param parameterName
     * @param x
     * @throws SQLException the SQL exception
     */
    @Override
    public void set(CallableStatement stmt, String parameterName, T x) throws SQLException {
        stmt.setString(parameterName, stringOf(x));
    }

    /**
     *
     * @param stmt
     * @param columnIndex
     * @param x
     * @param sqlTypeOrLength
     * @throws SQLException the SQL exception
     */
    @Override
    public void set(PreparedStatement stmt, int columnIndex, T x, int sqlTypeOrLength) throws SQLException {
        this.set(stmt, columnIndex, x);
    }

    /**
     *
     * @param stmt
     * @param parameterName
     * @param x
     * @param sqlTypeOrLength
     * @throws SQLException the SQL exception
     */
    @Override
    public void set(CallableStatement stmt, String parameterName, T x, int sqlTypeOrLength) throws SQLException {
        this.set(stmt, parameterName, x);
    }

    /**
     *
     * @param writer
     * @param x
     * @throws IOException Signals that an I/O exception has occurred.
     */
    @Override
    public void write(Writer writer, T x) throws IOException {
        if (x == null) {
            writer.write(NULL_CHAR_ARRAY);
        } else {
            writer.write(stringOf(x));
        }
    }

    /**
     *
     * @param writer
     * @param x
     * @param config
     * @throws IOException Signals that an I/O exception has occurred.
     */
    @Override
    public void writeCharacter(CharacterWriter writer, T x, SerializationConfig config) throws IOException {
        if (x == null) {
            writer.write(NULL_CHAR_ARRAY);
        } else {
            final char ch = config == null ? 0 : config.getStringQuotation();

            if (ch == 0) {
                writer.writeCharacter(stringOf(x));
            } else {
                writer.write(ch);
                writer.writeCharacter(stringOf(x));
                writer.write(ch);
            }
        }
    }

    /**
     * Collection 2 array.
     *
     * @param c
     * @return
     */
    @Override
    public T collection2Array(Collection c) {
        throw new UnsupportedOperationException(name() + " doesn't support collection2Array Operation");
    }

    /**
     * Array 2 collection.
     *
     * @param 
     * @param collClass
     * @param x
     * @return
     */
    @Override
    public  Collection array2Collection(Class collClass, T x) {
        throw new UnsupportedOperationException(name() + " doesn't support array2Collection Operation");
    }

    /**
     * Array 2 collection.
     *
     * @param 
     * @param resultCollection
     * @param x
     * @return
     */
    @Override
    public  Collection array2Collection(Collection resultCollection, T x) {
        throw new UnsupportedOperationException(name() + " doesn't support array2Collection Operation");
    }

    /**
     *
     * @param x
     * @return
     */
    @Override
    public int hashCode(T x) {
        return N.hashCode(x);
    }

    /**
     * Deep hash code.
     *
     * @param x
     * @return
     */
    @Override
    public int deepHashCode(T x) {
        return N.hashCode(x);
    }

    /**
     *
     * @param x
     * @param y
     * @return true, if successful
     */
    @Override
    public boolean equals(T x, T y) {
        return N.equals(x, y);
    }

    /**
     *
     * @param x
     * @param y
     * @return true, if successful
     */
    @Override
    public boolean deepEquals(T x, T y) {
        return N.equals(x, y);
    }

    /**
     *
     * @param x
     * @return
     */
    @Override
    public String toString(T x) {
        return N.toString(x);
    }

    /**
     * Deep to string.
     *
     * @param x
     * @return
     */
    @Override
    public String deepToString(T x) {
        return N.toString(x);
    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public int hashCode() {
        return name().hashCode();
    }

    /**
     * Returns true if the specified {@code} is a type and it's name equals with
     * this type's name.
     *
     * @param obj
     * @return boolean
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj instanceof AbstractType) {
            final AbstractType another = ((AbstractType) obj);
            return N.equals(another.name(), this.name()) && N.equals(another.declaringName(), this.declaringName()) && another.clazz().equals(this.clazz());
        }

        return false;
    }

    /**
     * Returns the type name.
     *
     * @return String
     */
    @Override
    public String toString() {
        return name();
    }

    /**
     *
     * @param st
     * @param separator
     * @return
     */
    protected static String[] split(String st, String separator) {
        String newValue = separatorConvertor.get(separator);

        return (newValue == null) ? st.split(separator) : st.split(newValue);
    }

    /**
     *
     *
     * @param cbuf
     * @param offset
     * @param len
     * @return
     * @throws NumberFormatException the number format exception
     * @see {@link Integer#parseInt(String)}
     */
    protected static int parseInt(final char[] cbuf, final int offset, final int len) throws NumberFormatException {
        if (offset < 0 || len < 0) {
            throw new IllegalArgumentException("'offset' and 'len' can't be negative");
        }

        if (len == 0 || (N.isNullOrEmpty(cbuf) && offset == 0)) {
            return 0;
        }

        switch (len) {
            case 1: {
                char ch = cbuf[offset];
                if (ch < '0' || ch > '9') {
                    throw new NumberFormatException("Invalid numeric String: \"" + ch + "\""); //NOSONAR
                }

                return ch - '0';
            }

            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:
            case 9: {
                boolean isNagtive = cbuf[offset] == '-';

                int result = 0;
                char ch = 0;

                for (int i = (cbuf[offset] == '-' || cbuf[offset] == '+') ? offset + 1 : offset, to = offset + len; i < to; i++) {
                    ch = cbuf[i];

                    if (ch < '0' || ch > '9') {
                        throw new NumberFormatException("Invalid numeric String: \"" + new String(cbuf, offset, len) + "\"");
                    }

                    result = result * 10 + (ch - '0');
                }

                return isNagtive ? -result : result;
            }

            default:
                return Numbers.toInt(new String(cbuf, offset, len));
        }
    }

    /**
     * Parses the long.
     *
     * @param cbuf
     * @param offset
     * @param len
     * @return
     * @throws NumberFormatException the number format exception
     * @see {@link Long#parseLong(String)}
     */
    protected static long parseLong(final char[] cbuf, final int offset, final int len) throws NumberFormatException {
        if (offset < 0 || len < 0) {
            throw new IllegalArgumentException("'offset' and 'len' can't be negative");
        }

        if (len == 0 || (N.isNullOrEmpty(cbuf) && offset == 0)) {
            return 0;
        }

        switch (len) {
            case 1: {
                char ch = cbuf[offset];
                if (ch < '0' || ch > '9') {
                    throw new NumberFormatException("Invalid numeric String: \"" + ch + "\"");
                }

                return ch - '0'; //NOSONAR
            }

            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:
            case 9:
            case 10:
            case 11:
            case 12:
            case 13:
            case 14:
            case 15:
            case 16:
            case 17:
            case 18: {
                boolean isNagtive = cbuf[offset] == '-';

                long result = 0;
                char ch = 0;

                for (int i = (cbuf[offset] == '-' || cbuf[offset] == '+') ? offset + 1 : offset, to = offset + len; i < to; i++) {
                    ch = cbuf[i];

                    if (ch < '0' || ch > '9') {
                        throw new NumberFormatException("Invalid numeric String: \"" + new String(cbuf, offset, len) + "\"");
                    }

                    result = result * 10 + (ch - '0');
                }

                return isNagtive ? -result : result;
            }

            default:
                return Numbers.toLong(new String(cbuf, offset, len));
        }
    }

    /**
     * Gets the column value.
     *
     * @param 
     * @param targetClass
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException the SQL exception
     */
    static  T getColumnValue(final Class targetClass, final ResultSet rs, final int columnIndex) throws SQLException {
        return N. typeOf(targetClass).get(rs, columnIndex);
    }

    /**
     * Gets the column value.
     *
     * @param 
     * @param targetClass
     * @param rs
     * @param columnLabel
     * @return
     * @throws SQLException the SQL exception
     */
    static  T getColumnValue(final Class targetClass, final ResultSet rs, final String columnLabel) throws SQLException {
        return N. typeOf(targetClass).get(rs, columnLabel);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy