Package org.eclipse.persistence.internal.dynamic

Source Code of org.eclipse.persistence.internal.dynamic.DynamicTypeInstantiationPolicy

/*******************************************************************************
* Copyright (c) 1998, 2009 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
*     dclarke - Dynamic Persistence INCUBATION - Enhancement 200045
*               http://wiki.eclipse.org/EclipseLink/Development/Dynamic
*    
* This code is being developed under INCUBATION and is not currently included
* in the automated EclipseLink build. The API in this code may change, or
* may never be included in the product. Please provide feedback through mailing
* lists or the bug database.
******************************************************************************/
package org.eclipse.persistence.internal.dynamic;

//javase imports
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

//EclipseLink imports
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.indirection.ValueHolder;
import org.eclipse.persistence.internal.descriptors.InstantiationPolicy;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.indirection.BasicIndirectionPolicy;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;

/**
* Simple {@link InstantiationPolicy} to call
* {@link DynamicTypeImpl#newDynamicEntity()}
*
* @author dclarke, mnorman
* @since EclipseLink 1.2
*/
public class DynamicTypeInstantiationPolicy extends InstantiationPolicy {

    private DynamicTypeImpl type;

    /*
     * Needed since InstantiationPolicy.defaultConstructor is not accessible
     */
    private transient Constructor<?> constructor = null;

    public DynamicTypeInstantiationPolicy(DynamicTypeImpl type) {
        this.type = type;
        this.descriptor = type.getDescriptor();
    }

    public DynamicTypeImpl getType() {
        return this.type;
    }

    /**
     * Lookup the constructor.
     */
    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        try {
            this.constructor = PrivilegedAccessHelper.getDeclaredConstructorFor(getType().getJavaClass(), new Class[] { DynamicTypeImpl.class }, true);
            this.constructor.setAccessible(true);
        } catch (NoSuchMethodException exception) {
            throw DescriptorException.noSuchMethodWhileInitializingInstantiationPolicy(getType().getName() + ".<Default Constructor>", getDescriptor(), exception);
        }
    }

    /**
     * Using privileged reflection create a new instance of the dynamic type
     * passing in this {@link DynamicTypeImpl} so the dynamic entity can have a
     * reference to its type. After creation initialize all required attributes.
     *
     * @see DynamicTypeInstantiationPolicy
     * @return new DynamicEntity with initialized attributes
     */
    /*
     * It would be easier to subclass InstantiationPolicy if its build methods
     * accepted an Object[] of args or requested the args from the policy. This
     * would avoid the large block of code below required to pass the type into
     * the constructor. Enhancement 288918 filed
     */
    @Override
    public Object buildNewInstance() {
        DynamicEntityImpl entity = null;

        try {
            entity = (DynamicEntityImpl) PrivilegedAccessHelper.invokeConstructor(this.getTypeConstructor(), new Object[] { getType() });
        } catch (InvocationTargetException exception) {
            throw DescriptorException.targetInvocationWhileConstructorInstantiation(this.getDescriptor(), exception);
        } catch (IllegalAccessException exception) {
            throw DescriptorException.illegalAccessWhileConstructorInstantiation(this.getDescriptor(), exception);
        } catch (InstantiationException exception) {
            throw DescriptorException.instantiationWhileConstructorInstantiation(this.getDescriptor(), exception);
        } catch (NoSuchMethodError exception) {
            // This exception is not documented but gets thrown.
            throw DescriptorException.noSuchMethodWhileConstructorInstantiation(this.getDescriptor(), exception);
        } catch (NullPointerException exception) {
            // Some JVMs will throw a NULL pointer exception here
            throw DescriptorException.nullPointerWhileConstructorInstantiation(this.getDescriptor(), exception);
        }

        for (DatabaseMapping mapping : getType().getMappingsRequiringInitialization()) {
            initializeValue(mapping, entity);
        }

        return entity;
    }

    /**
     * Initialize the default value handling primitives, collections and
     * indirection.
     *
     * @param mapping
     * @param entity
     */
    private void initializeValue(DatabaseMapping mapping, DynamicEntityImpl entity) {
        Object value = null;

        if (mapping.isDirectToFieldMapping() && mapping.getAttributeClassification().isPrimitive()) {
            Class<?> primClass = mapping.getAttributeClassification();

            if (primClass == ClassConstants.PBOOLEAN) {
                value = false;
            } else if (primClass == ClassConstants.PINT) {
                value = 0;
            } else if (primClass == ClassConstants.PLONG) {
                value = 0L;
            } else if (primClass == ClassConstants.PCHAR) {
                value = Character.MIN_VALUE;
            } else if (primClass == ClassConstants.PDOUBLE) {
                value = 0.0d;
            } else if (primClass == ClassConstants.PFLOAT) {
                value = 0.0f;
            } else if (primClass == ClassConstants.PSHORT) {
                value = Short.MIN_VALUE;
            } else if (primClass == ClassConstants.PBYTE) {
                value = Byte.MIN_VALUE;
            }
        } else if (mapping.isForeignReferenceMapping()) {
            ForeignReferenceMapping refMapping = (ForeignReferenceMapping) mapping;

            if (refMapping.usesIndirection() && refMapping.getIndirectionPolicy() instanceof BasicIndirectionPolicy) {
                value = new ValueHolder(value);
            } else if (refMapping.isCollectionMapping()) {
                value = ((CollectionMapping) refMapping).getContainerPolicy().containerInstance();
            }
        } else if (mapping.isAggregateObjectMapping()) {
            value = mapping.getReferenceDescriptor().getObjectBuilder().buildNewInstance();
        }

        mapping.setAttributeValueInObject(entity, value);
    }

    /**
     * Return the default (zero-argument) constructor for the descriptor class.
     */
    protected Constructor<?> getTypeConstructor() throws DescriptorException {
        if (this.constructor == null) {
            initialize(null);
        }
        return this.constructor;
    }

}
TOP

Related Classes of org.eclipse.persistence.internal.dynamic.DynamicTypeInstantiationPolicy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.