Search in sources :

Example 41 with ApiAdapter

use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.

the class ExecutionContextImpl method persistObjectInternal.

/**
 * Method to make an object persistent which should be called from internal calls only.
 * All PM/EM calls should go via persistObject(Object obj).
 * @param obj The object
 * @param preInsertChanges Any changes to make before inserting
 * @param ownerOP ObjectProvider of the owner when embedded
 * @param ownerFieldNum Field number in the owner where this is embedded (or -1 if not embedded)
 * @param objectType Type of object (see org.datanucleus.ObjectProvider, e.g ObjectProvider.PC)
 * @return The persisted object
 * @throws NucleusUserException if the object is managed by a different manager
 */
public <T> T persistObjectInternal(T obj, FieldValues preInsertChanges, ObjectProvider ownerOP, int ownerFieldNum, int objectType) {
    if (obj == null) {
        return null;
    }
    // TODO Support embeddedOwner/objectType, so we can add ObjectProvider for embedded objects here
    ApiAdapter api = getApiAdapter();
    // Id of the object that was persisted during this process (if any)
    Object id = null;
    try {
        clr.setPrimary(obj.getClass().getClassLoader());
        assertClassPersistable(obj.getClass());
        ExecutionContext ec = api.getExecutionContext(obj);
        if (ec != null && ec != this) {
            // Object managed by a different manager
            throw new NucleusUserException(Localiser.msg("010007", obj));
        }
        boolean cacheable = false;
        // Persisted object is the passed in pc (unless being attached as a copy)
        T persistedPc = obj;
        if (api.isDetached(obj)) {
            // Detached : attach it
            assertDetachable(obj);
            if (getBooleanProperty(PropertyNames.PROPERTY_COPY_ON_ATTACH)) {
                // Attach a copy and return the copy
                persistedPc = attachObjectCopy(ownerOP, obj, api.getIdForObject(obj) == null);
            } else {
                // Attach the object
                attachObject(ownerOP, obj, api.getIdForObject(obj) == null);
                persistedPc = obj;
            }
        } else if (api.isTransactional(obj) && !api.isPersistent(obj)) {
            // TransientTransactional : persist it
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
            }
            ObjectProvider op = findObjectProvider(obj);
            if (op == null) {
                throw new NucleusUserException(Localiser.msg("010007", getApiAdapter().getIdForObject(obj)));
            }
            op.makePersistentTransactionalTransient();
        } else if (!api.isPersistent(obj)) {
            // Transient : persist it
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
            }
            boolean merged = false;
            ThreadContextInfo threadInfo = acquireThreadContextInfo();
            try {
                if (threadInfo.merging) {
                    AbstractClassMetaData cmd = getMetaDataManager().getMetaDataForClass(obj.getClass(), clr);
                    if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                        Object transientId = nucCtx.getIdentityManager().getApplicationId(obj, cmd);
                        if (transientId != null) {
                            // User has set id field(s) so find the datastore object (if exists)
                            T existingObj = (T) findObject(transientId, true, true, cmd.getFullClassName());
                            ObjectProvider existingOP = findObjectProvider(existingObj);
                            existingOP.attach(obj);
                            id = transientId;
                            merged = true;
                            persistedPc = existingObj;
                        }
                    }
                    cacheable = nucCtx.isClassCacheable(cmd);
                }
            } catch (NucleusObjectNotFoundException onfe) {
            // Object with this id doesn't exist, so just persist the transient (below)
            } finally {
                releaseThreadContextInfo();
            }
            if (!merged) {
                ObjectProvider<T> op = findObjectProvider(obj);
                if (op == null) {
                    if ((objectType == ObjectProvider.EMBEDDED_COLLECTION_ELEMENT_PC || objectType == ObjectProvider.EMBEDDED_MAP_KEY_PC || objectType == ObjectProvider.EMBEDDED_MAP_VALUE_PC || objectType == ObjectProvider.EMBEDDED_PC) && ownerOP != null) {
                        // SCO object
                        op = nucCtx.getObjectProviderFactory().newForEmbedded(this, obj, false, ownerOP, ownerFieldNum);
                        op.setPcObjectType((short) objectType);
                        op.makePersistent();
                        id = op.getInternalObjectId();
                    } else {
                        // FCO object
                        op = nucCtx.getObjectProviderFactory().newForPersistentNew(this, obj, preInsertChanges);
                        op.makePersistent();
                        id = op.getInternalObjectId();
                    }
                } else {
                    if (op.getReferencedPC() == null) {
                        // Persist it
                        op.makePersistent();
                        id = op.getInternalObjectId();
                    } else {
                        // Being attached, so use the attached object
                        persistedPc = op.getReferencedPC();
                    }
                }
                if (op != null) {
                    cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
                }
            }
        } else if (api.isPersistent(obj) && api.getIdForObject(obj) == null) {
            // Should we be making a copy of the object here ?
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
            }
            ObjectProvider op = findObjectProvider(obj);
            op.makePersistent();
            id = op.getInternalObjectId();
            cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
        } else if (api.isDeleted(obj)) {
            // Deleted : (re)-persist it (permitted in JPA, but not JDO - see ObjectProvider)
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
            }
            ObjectProvider op = findObjectProvider(obj);
            op.makePersistent();
            id = op.getInternalObjectId();
            cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
        } else {
            if (api.isPersistent(obj) && api.isTransactional(obj) && api.isDirty(obj) && isDelayDatastoreOperationsEnabled()) {
                // Object provisionally persistent (but not in datastore) so re-run reachability maybe
                if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                    NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
                }
                ObjectProvider op = findObjectProvider(obj);
                op.makePersistent();
                id = op.getInternalObjectId();
                cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
            }
        }
        if (id != null && l2CacheTxIds != null && cacheable) {
            l2CacheTxIds.add(id);
        }
        return persistedPc;
    } finally {
        clr.unsetPrimary();
    }
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ObjectProvider(org.datanucleus.state.ObjectProvider) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Example 42 with ApiAdapter

use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.

the class ExecutionContextImpl method processNontransactionalAtomicChanges.

/**
 * Handler for all outstanding changes to be "committed" atomically.
 * If a transaction is active, non-tx writes are disabled, or atomic updates not enabled then will do nothing.
 * Otherwise will flush any updates that are outstanding (updates to an object), will perform detachAllOnCommit
 * if enabled (so user always has detached objects), update objects in any L2 cache, and migrates any
 * objects through lifecycle changes.
 * Is similar in content to "flush"+"preCommit"+"postCommit"
 * Note that this handling for updates is not part of standard JDO which expects non-tx updates to migrate an
 * object to P_NONTRANS_DIRTY rather than committing it directly.
 * TODO If any update fails we should throw the appropriate exception for the API
 */
protected void processNontransactionalAtomicChanges() {
    if (tx.isActive() || !tx.getNontransactionalWrite() || !tx.getNontransactionalWriteAutoCommit()) {
        return;
    }
    if (!dirtyOPs.isEmpty()) {
        // Make sure all non-tx dirty objects are enlisted so they get lifecycle changes
        for (ObjectProvider op : dirtyOPs) {
            if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
                NucleusLogger.TRANSACTION.debug(Localiser.msg("015017", StringUtils.toJVMIDString(op.getObject()), op.getInternalObjectId().toString()));
            }
            enlistedOPCache.put(op.getInternalObjectId(), op);
        }
        // Flush any outstanding changes to the datastore
        flushInternal(true);
        if (l2CacheEnabled) {
            // L2 caching of enlisted objects
            performLevel2CacheUpdateAtCommit();
        }
        if (properties.getFrequentProperties().getDetachAllOnCommit()) {
            // "detach-on-commit"
            performDetachAllOnTxnEndPreparation();
            performDetachAllOnTxnEnd();
        }
        // Make sure lifecycle changes take place to all "enlisted" objects
        List failures = null;
        try {
            // "commit" all enlisted ObjectProviders
            ApiAdapter api = getApiAdapter();
            ObjectProvider[] ops = enlistedOPCache.values().toArray(new ObjectProvider[enlistedOPCache.size()]);
            for (int i = 0; i < ops.length; ++i) {
                try {
                    // Run through "postCommit" to migrate the lifecycle state
                    if (ops[i] != null && ops[i].getObject() != null && api.isPersistent(ops[i].getObject()) && api.isDirty(ops[i].getObject())) {
                        ops[i].postCommit(getTransaction());
                    } else {
                        NucleusLogger.PERSISTENCE.debug(">> Atomic nontransactional processing : Not performing postCommit on " + ops[i]);
                    }
                } catch (RuntimeException e) {
                    if (failures == null) {
                        failures = new ArrayList();
                    }
                    failures.add(e);
                }
            }
        } finally {
            resetTransactionalVariables();
        }
        if (failures != null && !failures.isEmpty()) {
            throw new CommitStateTransitionException((Exception[]) failures.toArray(new Exception[failures.size()]));
        }
    }
    if (nontxProcessedOPs != null && !nontxProcessedOPs.isEmpty()) {
        for (ObjectProvider op : nontxProcessedOPs) {
            if (op != null && op.getLifecycleState() != null && op.getLifecycleState().isDeleted()) {
                removeObjectFromLevel1Cache(op.getInternalObjectId());
                removeObjectFromLevel2Cache(op.getInternalObjectId());
            }
        }
        nontxProcessedOPs.clear();
    }
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) CommitStateTransitionException(org.datanucleus.exceptions.CommitStateTransitionException) ArrayList(java.util.ArrayList) ObjectProvider(org.datanucleus.state.ObjectProvider) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) ClassNotDetachableException(org.datanucleus.exceptions.ClassNotDetachableException) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) RollbackStateTransitionException(org.datanucleus.exceptions.RollbackStateTransitionException) NucleusException(org.datanucleus.exceptions.NucleusException) NucleusFatalUserException(org.datanucleus.exceptions.NucleusFatalUserException) ClassNotPersistableException(org.datanucleus.exceptions.ClassNotPersistableException) NoPersistenceInformationException(org.datanucleus.exceptions.NoPersistenceInformationException) TransactionActiveOnCloseException(org.datanucleus.exceptions.TransactionActiveOnCloseException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassNotResolvedException(org.datanucleus.exceptions.ClassNotResolvedException) NucleusOptimisticException(org.datanucleus.exceptions.NucleusOptimisticException) CommitStateTransitionException(org.datanucleus.exceptions.CommitStateTransitionException) TransactionNotActiveException(org.datanucleus.exceptions.TransactionNotActiveException) ObjectDetachedException(org.datanucleus.exceptions.ObjectDetachedException)

Example 43 with ApiAdapter

use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.

the class AbstractClassMetaData method validateObjectIdClass.

/**
 * Validate the objectid-class of this class.
 * @param clr ClassLoader resolver
 */
protected void validateObjectIdClass(ClassLoaderResolver clr) {
    if (getPersistableSuperclass() == null) {
        // Only check root persistable class PK
        if (objectidClass != null) {
            ApiAdapter api = mmgr.getApiAdapter();
            Class obj_cls = null;
            try {
                // Load the class, using the same class loader resolver as this class
                obj_cls = clr.classForName(objectidClass);
            } catch (ClassNotResolvedException cnre) {
                // ObjectIdClass not found
                throw new InvalidClassMetaDataException("044079", fullName, objectidClass);
            }
            boolean validated = false;
            Set<Throwable> errors = new HashSet<>();
            try {
                // Check against the API Adapter in use for this MetaData
                if (api.isValidPrimaryKeyClass(obj_cls, this, clr, getNoOfPopulatedPKMembers(), mmgr)) {
                    validated = true;
                }
            } catch (NucleusException ex) {
                errors.add(ex);
            }
            if (!validated) {
                // This needs coordinating with the test expectations in the enhancer unit tests.
                throw new NucleusUserException(Localiser.msg("019016", getFullClassName(), obj_cls.getName()), errors.toArray(new Throwable[errors.size()]));
            }
        }
    }
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) NucleusException(org.datanucleus.exceptions.NucleusException) ClassNotResolvedException(org.datanucleus.exceptions.ClassNotResolvedException) HashSet(java.util.HashSet)

Example 44 with ApiAdapter

use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.

the class AbstractMemberMetaData method populate.

/**
 * Method to provide the details of the field being represented by this MetaData hence populating
 * certain parts of the MetaData. This is used to firstly provide defaults for attributes that aren't
 * specified in the MetaData, and secondly to report any errors with attributes that have been specifed
 * that are inconsistent with the field being represented.
 * Either a field or a method should be passed in (one or the other) depending on what is being represented
 * by this "member".
 * @param clr ClassLoaderResolver to use for any class loading
 * @param field Field that we are representing (if it's a field)
 * @param method Method(property) that we are representing (if it's a method).
 * @param primary the primary ClassLoader to use (or null)
 * @param mmgr MetaData manager
 */
public synchronized void populate(ClassLoaderResolver clr, Field field, Method method, ClassLoader primary, MetaDataManager mmgr) {
    if (isPopulated() || isInitialised()) {
        return;
    }
    // Set defaults for cascading when not yet set
    ApiAdapter apiAdapter = mmgr.getNucleusContext().getApiAdapter();
    if (cascadePersist == null) {
        cascadePersist = apiAdapter.getDefaultCascadePersistForField();
    }
    if (cascadeUpdate == null) {
        cascadeUpdate = apiAdapter.getDefaultCascadeUpdateForField();
    }
    if (cascadeDelete == null) {
        cascadeDelete = apiAdapter.getDefaultCascadeDeleteForField();
    }
    if (cascadeDetach == null) {
        cascadeDetach = apiAdapter.getDefaultCascadeDetachForField();
    }
    if (cascadeRefresh == null) {
        cascadeRefresh = apiAdapter.getDefaultCascadeRefreshForField();
    }
    if (field == null && method == null) {
        NucleusLogger.METADATA.error(Localiser.msg("044106", getClassName(), getName()));
        throw new InvalidMemberMetaDataException("044106", getClassName(), getName());
    }
    // No class loader, so use System
    if (clr == null) {
        NucleusLogger.METADATA.warn(Localiser.msg("044067", name, getClassName(true)));
        clr = mmgr.getNucleusContext().getClassLoaderResolver(null);
    }
    memberRepresented = field != null ? field : method;
    if (type == null) {
        // Type not yet set so set from field/method (will only be set if we are imposing the type due to Java generics TypeVariable usage)
        if (field != null) {
            this.type = field.getType();
        } else if (method != null) {
            this.type = method.getReturnType();
        }
    }
    if (className != null) {
        // Property is overriding a superclass property, so check that it is valid
        Class thisClass = null;
        if (parent instanceof EmbeddedMetaData) {
            // <embedded> is contained in a <field>, <element>, <key>, <value>
            // but could be multiple levels deep so adopt a generic strategy for finding the parent class
            MetaData superMd = parent.getParent();
            thisClass = ((AbstractMemberMetaData) superMd).getType();
        } else {
            // Overriding field in a superclass of this class
            try {
                thisClass = clr.classForName(getAbstractClassMetaData().getPackageName() + "." + getAbstractClassMetaData().getName());
            } catch (ClassNotResolvedException cnre) {
            // Do nothing
            }
        }
        Class fieldClass = null;
        try {
            fieldClass = clr.classForName(className);
        } catch (ClassNotResolvedException cnre) {
            try {
                fieldClass = clr.classForName(getAbstractClassMetaData().getPackageName() + "." + className);
                className = getAbstractClassMetaData().getPackageName() + "." + className;
            } catch (ClassNotResolvedException cnre2) {
                NucleusLogger.METADATA.error(Localiser.msg("044113", getClassName(), getName(), className));
                NucleusException ne = new InvalidMemberMetaDataException("044113", getClassName(), getName(), className);
                ne.setNestedException(cnre);
                throw ne;
            }
        }
        if (fieldClass != null && !fieldClass.isAssignableFrom(thisClass)) {
            // TODO We could also check if persistable, but won't work when enhancing
            NucleusLogger.METADATA.error(Localiser.msg("044114", getClassName(), getName(), className));
            throw new InvalidMemberMetaDataException("044114", getClassName(), getName(), className);
        }
    }
    if (primaryKey == null) {
        // Primary key not set by user so initialise it to false
        primaryKey = Boolean.FALSE;
    }
    // Update "embedded" based on type
    if (primaryKey == Boolean.FALSE && embedded == null) {
        Class element_type = getType();
        if (element_type.isArray()) {
            element_type = element_type.getComponentType();
            if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(element_type)) {
                embedded = Boolean.TRUE;
            }
        } else if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(element_type)) {
            embedded = Boolean.TRUE;
        }
    }
    if (embedded == null) {
        embedded = Boolean.FALSE;
    }
    // Update "persistence-modifier" according to type etc
    if (FieldPersistenceModifier.DEFAULT.equals(persistenceModifier)) {
        if (getTypeConverterName() != null) {
            // Explicitly set a converter, so assume it is persistent
            persistenceModifier = FieldPersistenceModifier.PERSISTENT;
        } else {
            boolean isPcClass = getType().isArray() ? isFieldArrayTypePersistable(mmgr) : mmgr.isFieldTypePersistable(type);
            if (!isPcClass) {
                if (getType().isArray() && getType().getComponentType().isInterface()) {
                    isPcClass = mmgr.getMetaDataForClassInternal(getType().getComponentType(), clr) != null;
                } else if (getType().isInterface()) {
                    isPcClass = mmgr.getMetaDataForClassInternal(getType(), clr) != null;
                }
            }
            persistenceModifier = getDefaultFieldPersistenceModifier(getType(), memberRepresented.getModifiers(), isPcClass, mmgr);
        }
    }
    // TODO If this field is NONE in superclass, make it NONE here too
    // If type is a container, load create the metadata. The field will be handled as a container if it
    // has a ContainerHandler registered against it.
    TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
    ContainerHandler containerHandler = typeMgr.getContainerHandler(type);
    if (containerHandler == null) {
        // No container handler registered for this type
        if (hasContainer()) {
            // Container metadata specified on a type that is not a valid or supported container
            NucleusLogger.METADATA.error(Localiser.msg("044212", getClassName(), getName(), type));
            NucleusException ne = new InvalidMemberMetaDataException("044212", getClassName(), getName(), type);
            throw ne;
        }
    } else {
        // Field is a container type
        if (!hasContainer()) {
            // No container metadata has not been specified yet, create a default empty one
            setContainer(containerHandler.newMetaData());
        }
        containerHandler.populateMetaData(clr, primary, this);
    }
    // Update "default-fetch-group" according to type
    if (defaultFetchGroup == null && persistenceModifier.equals(FieldPersistenceModifier.NONE)) {
        defaultFetchGroup = Boolean.FALSE;
    } else if (defaultFetchGroup == null && persistenceModifier.equals(FieldPersistenceModifier.TRANSACTIONAL)) {
        defaultFetchGroup = Boolean.FALSE;
    } else if (defaultFetchGroup == null) {
        defaultFetchGroup = Boolean.FALSE;
        if (!primaryKey.equals(Boolean.TRUE)) {
            if (hasContainer() && containerHandler != null) {
                defaultFetchGroup = containerHandler.isDefaultFetchGroup(clr, typeMgr, this);
            } else if (typeMgr.isDefaultFetchGroup(getType())) {
                // If still not determined rely on the type
                defaultFetchGroup = Boolean.TRUE;
            }
        }
    }
    // Field is not specified as "persistent" yet has DFG or primary-key !
    if (persistenceModifier.equals(FieldPersistenceModifier.TRANSACTIONAL) || persistenceModifier.equals(FieldPersistenceModifier.NONE)) {
        if (defaultFetchGroup == Boolean.TRUE || primaryKey == Boolean.TRUE) {
            throw new InvalidMemberMetaDataException("044109", getClassName(), name, this.getType().getName(), persistenceModifier.toString());
        }
    }
    if (storeInLob) {
        // Set up the jdbcType/serialized settings according to the field type in line with JPA
        boolean useClob = false;
        if (type == String.class || (type.isArray() && type.getComponentType() == Character.class) || (type.isArray() && type.getComponentType() == char.class)) {
            useClob = true;
            if (columns == null || columns.isEmpty()) {
                // Create a CLOB column. What if the RDBMS doesn't support CLOB ?
                ColumnMetaData colmd = new ColumnMetaData();
                colmd.setName(column);
                colmd.setJdbcType("CLOB");
                addColumn(colmd);
            } else {
                ColumnMetaData colmd = columns.get(0);
                colmd.setJdbcType("CLOB");
            }
        }
        if (!useClob) {
            serialized = Boolean.TRUE;
        }
    }
    if (!mmgr.isDefaultNullable() && !hasContainer()) {
        // Find column metadata definition, creating one if not specified
        ColumnMetaData colMmd;
        if (columns == null || columns.isEmpty()) {
            newColumnMetaData();
        }
        colMmd = getColumnMetaData()[0];
        // Set column not-null by default
        if (colMmd.getAllowsNull() == null) {
            colMmd.setAllowsNull(Boolean.FALSE);
        }
    }
    if (this.containerMetaData != null && this.dependent != null) {
        // Check for invalid dependent field specifications
        NucleusLogger.METADATA.error(Localiser.msg("044110", getClassName(), getName(), ((ClassMetaData) this.parent).getName()));
        throw new InvalidMemberMetaDataException("044110", getClassName(), getName(), ((ClassMetaData) this.parent).getName());
    }
    if (embedded == Boolean.TRUE && embeddedMetaData == null) {
        // User specified "embedded" on the member, yet no embedded definition so add one TODO Omit this, since we should only use when provided
        AbstractClassMetaData memberCmd = mmgr.getMetaDataForClassInternal(getType(), clr);
        if (memberCmd != null) {
            embeddedMetaData = new EmbeddedMetaData();
            embeddedMetaData.setParent(this);
        }
    }
    if (embeddedMetaData != null) {
        // Update with any extensions (for lack of features in JPA)
        if (hasExtension("null-indicator-column")) {
            embeddedMetaData.setNullIndicatorColumn(getValueForExtension("null-indicator-column"));
            if (hasExtension("null-indicator-value")) {
                embeddedMetaData.setNullIndicatorValue(getValueForExtension("null-indicator-value"));
            }
        }
        // Populate any embedded object
        embeddedMetaData.populate(clr, primary);
        embedded = Boolean.TRUE;
    }
    if (containerMetaData != null && persistenceModifier == FieldPersistenceModifier.PERSISTENT) {
        // Populate any container
        if (containerMetaData instanceof CollectionMetaData) {
        // if (cascadeDelete)
        // {
        // // User has set cascade-delete (JPA) so set the element as dependent
        // getCollection().element.dependent = Boolean.TRUE;
        // }
        // getCollection().populate(clr, primary, mmgr);
        } else if (containerMetaData instanceof MapMetaData) {
        // String keyCascadeVal = getValueForExtension("cascade-delete-key");
        // if (cascadeDelete)
        // {
        // // User has set cascade-delete (JPA) so set the value as dependent
        // getMap().key.dependent = Boolean.FALSE; // JPA spec doesn't define what this should be
        // getMap().value.dependent = Boolean.TRUE;
        // }
        // if (keyCascadeVal != null)
        // {
        // if (keyCascadeVal.equalsIgnoreCase("true"))
        // {
        // getMap().key.dependent = Boolean.TRUE;
        // }
        // else
        // {
        // getMap().key.dependent = Boolean.FALSE;
        // }
        // }
        // getMap().populate(clr, primary, mmgr);
        } else if (containerMetaData instanceof ArrayMetaData) {
        // if (cascadeDelete)
        // {
        // // User has set cascade-delete (JPA) so set the element as dependent
        // getArray().element.dependent = Boolean.TRUE;
        // }
        // getArray().populate(clr, primary, mmgr);
        }
    }
    if (mmgr.isFieldTypePersistable(type) && cascadeDelete) {
        setDependent(true);
    }
    if (hasExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES)) {
        // Check the validity of the implementation-classes and qualify them where required.
        StringBuilder str = new StringBuilder();
        String[] implTypes = getValuesForExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES);
        for (int i = 0; i < implTypes.length; i++) {
            String implTypeName = ClassUtils.createFullClassName(getAbstractClassMetaData().getPackageName(), implTypes[i]);
            if (i > 0) {
                str.append(",");
            }
            try {
                clr.classForName(implTypeName);
                str.append(implTypeName);
            } catch (ClassNotResolvedException cnre) {
                try {
                    // Maybe the user specified a java.lang class without fully-qualifying it
                    // This is beyond the scope of the JDO spec which expects java.lang cases to be fully-qualified
                    String langClassName = ClassUtils.getJavaLangClassForType(implTypeName);
                    clr.classForName(langClassName);
                    str.append(langClassName);
                } catch (ClassNotResolvedException cnre2) {
                    // Implementation type not found
                    throw new InvalidMemberMetaDataException("044116", getClassName(), getName(), implTypes[i]);
                }
            }
        }
        // Replace with this new value
        addExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES, str.toString());
    }
    // Set up persistence flags for enhancement process
    byte serializable = 0;
    if (Serializable.class.isAssignableFrom(getType()) || getType().isPrimitive()) {
        serializable = Persistable.SERIALIZABLE;
    }
    if (FieldPersistenceModifier.NONE.equals(persistenceModifier)) {
        persistenceFlags = 0;
    } else if (FieldPersistenceModifier.TRANSACTIONAL.equals(persistenceModifier) && Modifier.isTransient(memberRepresented.getModifiers())) {
        persistenceFlags = (byte) (Persistable.CHECK_WRITE | serializable);
    } else if (primaryKey.booleanValue()) {
        persistenceFlags = (byte) (Persistable.MEDIATE_WRITE | serializable);
    } else if (defaultFetchGroup.booleanValue()) {
        persistenceFlags = (byte) (Persistable.CHECK_READ | Persistable.CHECK_WRITE | serializable);
    } else if (!defaultFetchGroup.booleanValue()) {
        persistenceFlags = (byte) (Persistable.MEDIATE_READ | Persistable.MEDIATE_WRITE | serializable);
    } else {
        persistenceFlags = 0;
    }
    // Set fields that are not relations
    if (persistenceModifier != FieldPersistenceModifier.PERSISTENT) {
        // Not a relation field so set relation information
        relationType = RelationType.NONE;
    } else if (containerMetaData == null && !mmgr.isFieldTypePersistable(type)) {
        if (!type.getName().equals(ClassNameConstants.Object) && !type.isInterface()) {
            // Not a container field, not a persistable type, nor a reference type so not a relation field
            relationType = RelationType.NONE;
        }
    }
    if (serialized == Boolean.TRUE && hasExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME)) {
        NucleusLogger.METADATA.warn(Localiser.msg("044127", getClassName(), getName(), getValueForExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME)));
        serialized = Boolean.FALSE;
    }
    setPopulated();
}
Also used : Serializable(java.io.Serializable) ApiAdapter(org.datanucleus.api.ApiAdapter) ClassNotResolvedException(org.datanucleus.exceptions.ClassNotResolvedException) ContainerHandler(org.datanucleus.store.types.ContainerHandler) TypeManager(org.datanucleus.store.types.TypeManager) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 45 with ApiAdapter

use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.

the class IdentityUtils method getApplicationIdentityForResultSetRow.

/**
 * Method to return the object application identity for a row of the result set.
 * If the class isn't using application identity then returns null
 * @param ec Execution Context
 * @param cmd Metadata for the class
 * @param pcClass The class required
 * @param inheritanceCheck Whether need an inheritance check (may be for a subclass)
 * @param resultsFM FieldManager servicing the results
 * @return The identity (if found) or null (if either not sure of inheritance, or not known).
 */
public static Object getApplicationIdentityForResultSetRow(ExecutionContext ec, AbstractClassMetaData cmd, Class pcClass, boolean inheritanceCheck, FieldManager resultsFM) {
    if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        if (pcClass == null) {
            pcClass = ec.getClassLoaderResolver().classForName(cmd.getFullClassName());
        }
        ApiAdapter api = ec.getApiAdapter();
        int[] pkFieldNums = cmd.getPKMemberPositions();
        Object[] pkFieldValues = new Object[pkFieldNums.length];
        for (int i = 0; i < pkFieldNums.length; i++) {
            AbstractMemberMetaData pkMmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[i]);
            if (pkMmd.getType() == int.class) {
                pkFieldValues[i] = resultsFM.fetchIntField(pkFieldNums[i]);
            } else if (pkMmd.getType() == short.class) {
                pkFieldValues[i] = resultsFM.fetchShortField(pkFieldNums[i]);
            } else if (pkMmd.getType() == long.class) {
                pkFieldValues[i] = resultsFM.fetchLongField(pkFieldNums[i]);
            } else if (pkMmd.getType() == char.class) {
                pkFieldValues[i] = resultsFM.fetchCharField(pkFieldNums[i]);
            } else if (pkMmd.getType() == boolean.class) {
                pkFieldValues[i] = resultsFM.fetchBooleanField(pkFieldNums[i]);
            } else if (pkMmd.getType() == byte.class) {
                pkFieldValues[i] = resultsFM.fetchByteField(pkFieldNums[i]);
            } else if (pkMmd.getType() == double.class) {
                pkFieldValues[i] = resultsFM.fetchDoubleField(pkFieldNums[i]);
            } else if (pkMmd.getType() == float.class) {
                pkFieldValues[i] = resultsFM.fetchFloatField(pkFieldNums[i]);
            } else if (pkMmd.getType() == String.class) {
                pkFieldValues[i] = resultsFM.fetchStringField(pkFieldNums[i]);
            } else {
                pkFieldValues[i] = resultsFM.fetchObjectField(pkFieldNums[i]);
            }
        }
        Class idClass = ec.getClassLoaderResolver().classForName(cmd.getObjectidClass());
        if (cmd.usesSingleFieldIdentityClass()) {
            // Create SingleField identity with query key value
            Object id = ec.getNucleusContext().getIdentityManager().getSingleFieldId(idClass, pcClass, pkFieldValues[0]);
            if (inheritanceCheck) {
                // Check if this identity exists in the cache(s)
                if (ec.hasIdentityInCache(id)) {
                    return id;
                }
                // Check if this id for any known subclasses is in the cache to save searching
                String[] subclasses = ec.getMetaDataManager().getSubclassesForClass(pcClass.getName(), true);
                if (subclasses != null) {
                    for (int i = 0; i < subclasses.length; i++) {
                        Object subid = ec.getNucleusContext().getIdentityManager().getSingleFieldId(idClass, ec.getClassLoaderResolver().classForName(subclasses[i]), IdentityUtils.getTargetKeyForSingleFieldIdentity(id));
                        if (ec.hasIdentityInCache(subid)) {
                            return subid;
                        }
                    }
                }
                // Check the inheritance with the store manager (may involve a trip to the datastore)
                String className = ec.getStoreManager().getClassNameForObjectID(id, ec.getClassLoaderResolver(), ec);
                return ec.getNucleusContext().getIdentityManager().getSingleFieldId(idClass, ec.getClassLoaderResolver().classForName(className), pkFieldValues[0]);
            }
            return id;
        }
        // Create user-defined PK class with PK field values
        try {
            // All user-defined PK classes have a default constructor
            Object id = idClass.newInstance();
            for (int i = 0; i < pkFieldNums.length; i++) {
                AbstractMemberMetaData pkMmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[i]);
                Object value = pkFieldValues[i];
                if (api.isPersistable(value)) {
                    // CompoundIdentity, so use id
                    value = api.getIdForObject(value);
                }
                if (pkMmd instanceof FieldMetaData) {
                    // Set the field directly (assumed to be public)
                    Field pkField = ClassUtils.getFieldForClass(idClass, pkMmd.getName());
                    pkField.set(id, value);
                } else {
                    // Use the setter
                    Method pkMethod = ClassUtils.getSetterMethodForClass(idClass, pkMmd.getName(), pkMmd.getType());
                    pkMethod.invoke(id, value);
                }
            }
            return id;
        } catch (Exception e) {
            return null;
        }
    }
    return null;
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) Method(java.lang.reflect.Method) NucleusException(org.datanucleus.exceptions.NucleusException) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) Field(java.lang.reflect.Field) FieldMetaData(org.datanucleus.metadata.FieldMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

ApiAdapter (org.datanucleus.api.ApiAdapter)53 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)19 ObjectProvider (org.datanucleus.state.ObjectProvider)16 ExecutionContext (org.datanucleus.ExecutionContext)12 Map (java.util.Map)11 NucleusException (org.datanucleus.exceptions.NucleusException)11 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)10 Iterator (java.util.Iterator)8 NucleusObjectNotFoundException (org.datanucleus.exceptions.NucleusObjectNotFoundException)8 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)8 Collection (java.util.Collection)7 HashMap (java.util.HashMap)7 RelationType (org.datanucleus.metadata.RelationType)7 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)7 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)6 ClassNotResolvedException (org.datanucleus.exceptions.ClassNotResolvedException)6 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)5 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)5 TypeManager (org.datanucleus.store.types.TypeManager)5 SortedMap (java.util.SortedMap)4