/*
 * 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 org.apache.commons.beanutils2;


import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.StreamCorruptedException;
import java.util.List;
import java.util.Map;


/**
 * <p>The metadata describing an individual property of a DynaBean.</p>
 *
 * <p>The meta contains an <em>optional</em> content type property ({@link #getContentType})
 * for use by mapped and iterated properties.
 * A mapped or iterated property may choose to indicate the type it expects.
 * The DynaBean implementation may choose to enforce this type on its entries.
 * Alternatively, an implementation may choose to ignore this property.
 * All keys for maps must be of type String so no meta data is needed for map keys.</p>
 *
 */

public class DynaProperty implements Serializable {

    

	private static final long serialVersionUID = -3084907613499830175L;
	/*
     * There are issues with serializing primitive class types on certain JVM versions
     * (including java 1.3).
     * This class uses a custom serialization implementation that writes an integer
     * for these primitive class.
     * This list of constants are the ones used in serialization.
     * If these values are changed, then older versions will no longer be read correctly
     */
    private static final int BOOLEAN_TYPE = 1;
    private static final int BYTE_TYPE = 2;
    private static final int CHAR_TYPE = 3;
    private static final int DOUBLE_TYPE = 4;
    private static final int FLOAT_TYPE = 5;
    private static final int INT_TYPE = 6;
    private static final int LONG_TYPE = 7;
    private static final int SHORT_TYPE = 8;


    


    /**
     * Construct a property that accepts any data type.
     *
     * @param name Name of the property being described
     */
    public DynaProperty(final String name) {

        this(name, Object.class);

    }


    /**
     * Construct a property of the specified data type.
     *
     * @param name Name of the property being described
     * @param type Java class representing the property data type
     */
    public DynaProperty(final String name, final Class<?> type) {

        super();
        this.name = name;
        this.type = type;
        if (type != null && type.isArray()) {
            this.contentType = type.getComponentType();
        }

    }

    /**
     * Construct an indexed or mapped {@code DynaProperty} that supports (pseudo)-introspection
     * of the content type.
     *
     * @param name Name of the property being described
     * @param type Java class representing the property data type
     * @param contentType Class that all indexed or mapped elements are instances of
     */
    public DynaProperty(final String name, final Class<?> type, final Class<?> contentType) {

        super();
        this.name = name;
        this.type = type;
        this.contentType = contentType;

    }

    

    /** Property name */
    protected String name = null;
    /**
     * Get the name of this property.
     * @return the name of the property
     */
    public String getName() {
        return this.name;
    }

    /** Property type */
    protected transient Class<?> type = null;
    /**
     * <p>Gets the Java class representing the data type of the underlying property
     * values.</p>
     *
     * <p>There are issues with serializing primitive class types on certain JVM versions
     * (including java 1.3).
     * Therefore, this field <strong>must not be serialized using the standard methods</strong>.</p>
     *
     * <p><strong>Please leave this field as {@code transient}</strong></p>
     *
     * @return the property type
     */
    public Class<?> getType() {
        return this.type;
    }


    /** The <em>(optional)</em> type of content elements for indexed {@code DynaProperty} */
    protected transient Class<?> contentType;
    /**
     * Gets the <em>(optional)</em> type of the indexed content for {@code DynaProperty}'s
     * that support this feature.
     *
     * <p>There are issues with serializing primitive class types on certain JVM versions
     * (including java 1.3).
     * Therefore, this field <strong>must not be serialized using the standard methods</strong>.</p>
     *
     * @return the Class for the content type if this is an indexed {@code DynaProperty}
     * and this feature is supported. Otherwise null.
     */
    public Class<?> getContentType() {
        return contentType;
    }

    


    /**
     * Does this property represent an indexed value (ie an array or List)?
     *
     * @return {@code true} if the property is indexed (i.e. is a List or
     * array), otherwise {@code false}
     */
    public boolean isIndexed() {

        if (type == null) {
            return false;
        } else if (type.isArray()) {
            return true;
        } else if (List.class.isAssignableFrom(type)) {
            return true;
        } else {
            return false;
        }

    }


    /**
     * Does this property represent a mapped value (ie a Map)?
     *
     * @return {@code true} if the property is a Map
     * otherwise {@code false}
     */
    public boolean isMapped() {

        if (type == null) {
            return false;
        }
        return Map.class.isAssignableFrom(type);

    }

    /**
     * Checks this instance against the specified Object for equality. Overrides the
     * default reference test for equality provided by {@link java.lang.Object#equals(Object)}
     * @param obj The object to compare to
     * @return {@code true} if object is a dyna property with the same name
     * type and content type, otherwise {@code false}
     * @since 1.8.0
     */
    @Override
    public boolean equals(final Object obj) {

        boolean result = false;

        result = obj == this;

        if (!result && obj instanceof DynaProperty) {
            final DynaProperty that = (DynaProperty) obj;
            result =
               (this.name == null ? that.name == null : this.name.equals(that.name)) &&
               (this.type == null ? that.type == null : this.type.equals(that.type)) &&
               (this.contentType == null ? that.contentType == null : this.contentType.equals(that.contentType));
        }

        return result;
    }

    /**
     * @return the hashcode for this dyna property
     * @see java.lang.Object#hashCode
     * @since 1.8.0
     */
    @Override
    public int hashCode() {

       int result = 1;

       result = result * 31 + (name == null ? 0 : name.hashCode());
       result = result * 31 + (type == null ? 0 : type.hashCode());
       result = result * 31 + (contentType == null ? 0 : contentType.hashCode());

       return result;
    }

    /**
     * Return a String representation of this Object.
     * @return a String representation of the dyna property
     */
    @Override
    public String toString() {

        final StringBuilder sb = new StringBuilder("DynaProperty[name=");
        sb.append(this.name);
        sb.append(",type=");
        sb.append(this.type);
        if (isMapped() || isIndexed()) {
            sb.append(" <").append(this.contentType).append(">");
        }
        sb.append("]");
        return sb.toString();

    }

    

    /**
     * Writes this object safely.
     * There are issues with serializing primitive class types on certain JVM versions
     * (including java 1.3).
     * This method provides a workaround.
     *
     * @param out {@link ObjectOutputStream} to write object to
     * @throws IOException if the object can't be written
     */
    private void writeObject(final ObjectOutputStream out) throws IOException {

        writeAnyClass(this.type,out);

        if (isMapped() || isIndexed()) {
            writeAnyClass(this.contentType,out);
        }

        // write out other values
        out.defaultWriteObject();
    }

    /**
     * Write a class using safe encoding to workaround java 1.3 serialization bug.
     */
    private void writeAnyClass(final Class<?> clazz, final ObjectOutputStream out) throws IOException {
        // safely write out any class
        int primitiveType = 0;
        if (Boolean.TYPE.equals(clazz)) {
            primitiveType = BOOLEAN_TYPE;
        } else if (Byte.TYPE.equals(clazz)) {
            primitiveType = BYTE_TYPE;
        } else if (Character.TYPE.equals(clazz)) {
            primitiveType = CHAR_TYPE;
        } else if (Double.TYPE.equals(clazz)) {
            primitiveType = DOUBLE_TYPE;
        } else if (Float.TYPE.equals(clazz)) {
            primitiveType = FLOAT_TYPE;
        } else if (Integer.TYPE.equals(clazz)) {
            primitiveType = INT_TYPE;
        } else if (Long.TYPE.equals(clazz)) {
            primitiveType = LONG_TYPE;
        } else if (Short.TYPE.equals(clazz)) {
            primitiveType = SHORT_TYPE;
        }

        if (primitiveType == 0) {
            // then it's not a primitive type
            out.writeBoolean(false);
            out.writeObject(clazz);
        } else {
            // we'll write out a constant instead
            out.writeBoolean(true);
            out.writeInt(primitiveType);
        }
    }

    /**
     * Reads field values for this object safely.
     * There are issues with serializing primitive class types on certain JVM versions
     * (including java 1.3).
     * This method provides a workaround.
     *
     * @param in {@link ObjectInputStream} to read object from
     * @throws StreamCorruptedException when the stream data values are outside expected range
     * @throws IOException if the input stream can't be read
     * @throws ClassNotFoundException When trying to read an object of class that is not on the classpath
     */
    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {

        this.type = readAnyClass(in);

        if (isMapped() || isIndexed()) {
            this.contentType = readAnyClass(in);
        }

        // read other values
        in.defaultReadObject();
    }


    /**
     * Reads a class using safe encoding to workaround java 1.3 serialization bug.
     */
    private Class<?> readAnyClass(final ObjectInputStream in) throws IOException, ClassNotFoundException {
        // read back type class safely
        if (in.readBoolean()) {
            // it's a type constant
            switch (in.readInt()) {

                case BOOLEAN_TYPE: return   Boolean.TYPE;
                case BYTE_TYPE:    return      Byte.TYPE;
                case CHAR_TYPE:    return Character.TYPE;
                case DOUBLE_TYPE:  return    Double.TYPE;
                case FLOAT_TYPE:   return     Float.TYPE;
                case INT_TYPE:     return   Integer.TYPE;
                case LONG_TYPE:    return      Long.TYPE;
                case SHORT_TYPE:   return     Short.TYPE;
                default:
                    // something's gone wrong
                    throw new StreamCorruptedException(
                        "Invalid primitive type. "
                        + "Check version of beanutils used to serialize is compatible.");

            }

        }
        // it's another class
        return (Class<?>) in.readObject();
    }
}
