Search in sources :

Example 6 with AbstractMethodAttribute

use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.

the class ProxyFactory method generateEmptyInstanceBytes.

private static byte[] generateEmptyInstanceBytes(String serializableClassName, ManagedViewTypeImplementor<?> managedViewTypeImplementor) {
    // Generate empty object serialization bytes according to https://www.javaworld.com/article/2072752/the-java-serialization-algorithm-revealed.html
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
        DataOutputStream oos = new DataOutputStream(baos);
        oos.writeShort(ObjectStreamConstants.STREAM_MAGIC);
        oos.writeShort(ObjectStreamConstants.STREAM_VERSION);
        // Start object
        oos.writeByte(ObjectStreamConstants.TC_OBJECT);
        // Class descriptor
        oos.writeByte(ObjectStreamConstants.TC_CLASSDESC);
        // Class name
        oos.writeUTF(serializableClassName);
        // Serial version UID of the class
        oos.writeLong(1L);
        // Supported flags
        oos.writeByte(ObjectStreamConstants.SC_SERIALIZABLE);
        List<List<SerializationField>> serializationFieldHierarchy = new ArrayList<>();
        List<SerializationField> serializationFields = new ArrayList<>();
        for (MethodAttribute<?, ?> attribute : managedViewTypeImplementor.getAttributes()) {
            serializationFields.add(new MetaSerializationField((AbstractMethodAttribute<?, ?>) attribute));
        }
        serializationFieldHierarchy.add(serializationFields);
        writeFields(serializationFields, oos);
        oos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);
        // TODO: foreign package supertypes?
        Class<?> superclass = managedViewTypeImplementor.getJavaType();
        if (!superclass.isInterface()) {
            while (superclass != Object.class) {
                // Class descriptor
                oos.writeByte(ObjectStreamConstants.TC_CLASSDESC);
                // Class name
                oos.writeUTF(superclass.getName());
                List<SerializationField> fields = new ArrayList<>();
                ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(superclass);
                for (ObjectStreamField field : objectStreamClass.getFields()) {
                    fields.add(new ObjectStreamFieldSerializationField(field));
                }
                if (Serializable.class.isAssignableFrom(superclass)) {
                    // Serial version UID of the class
                    oos.writeLong(objectStreamClass.getSerialVersionUID());
                    // Supported flags
                    oos.writeByte(ObjectStreamConstants.SC_SERIALIZABLE);
                } else {
                    // Serial version UID of the class
                    oos.writeLong(0L);
                    // Supported flags
                    oos.writeByte(0);
                }
                serializationFieldHierarchy.add(fields);
                writeFields(fields, oos);
                oos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);
                superclass = superclass.getSuperclass();
            }
        }
        oos.writeByte(ObjectStreamConstants.TC_NULL);
        for (List<SerializationField> fields : serializationFieldHierarchy) {
            for (SerializationField serializationField : fields) {
                if (serializationField.isPrimitive()) {
                    switch(serializationField.getType().getName()) {
                        case "int":
                            oos.writeInt(0);
                            break;
                        case "byte":
                            oos.writeByte(0);
                            break;
                        case "long":
                            oos.writeLong(0);
                            break;
                        case "float":
                            oos.writeFloat(0);
                            break;
                        case "double":
                            oos.writeDouble(0);
                            break;
                        case "short":
                            oos.writeShort(0);
                            break;
                        case "char":
                            oos.writeChar(0);
                            break;
                        case "boolean":
                            oos.writeBoolean(false);
                            break;
                        default:
                            throw new UnsupportedOperationException("Unsupported primitive type: " + serializationField.getType().getName());
                    }
                } else {
                    oos.writeByte(ObjectStreamConstants.TC_NULL);
                }
            }
        }
        oos.flush();
        return baos.toByteArray();
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}
Also used : DataOutputStream(java.io.DataOutputStream) ArrayList(java.util.ArrayList) ByteArrayOutputStream(java.io.ByteArrayOutputStream) InvocationTargetException(java.lang.reflect.InvocationTargetException) IOException(java.io.IOException) NotFoundException(javassist.NotFoundException) CannotCompileException(javassist.CannotCompileException) ObjectStreamField(java.io.ObjectStreamField) AbstractMethodAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute) ArrayList(java.util.ArrayList) List(java.util.List) RecordingList(com.blazebit.persistence.view.impl.collection.RecordingList) ObjectStreamClass(java.io.ObjectStreamClass)

Example 7 with AbstractMethodAttribute

use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.

the class EntityViewUpdaterImpl method createSingularAttributeFlusher.

private DirtyAttributeFlusher<?, ?, ?> createSingularAttributeFlusher(EntityViewManagerImpl evm, Map<Object, EntityViewUpdaterImpl> localCache, ManagedViewTypeImplementor<?> viewType, AbstractMethodAttribute<?, ?> attribute, EntityViewUpdaterImpl owner, String ownerMapping) {
    EntityMetamodel entityMetamodel = evm.getMetamodel().getEntityMetamodel();
    Class<?> entityClass = viewType.getEntityClass();
    String attributeName = attribute.getName();
    String attributeMapping = attribute.getMapping();
    AttributeAccessor entityAttributeAccessor = Accessors.forEntityMapping(evm, attribute);
    String attributeLocation = attribute.getLocation();
    boolean cascadePersist = attribute.isPersistCascaded();
    boolean cascadeUpdate = attribute.isUpdateCascaded();
    boolean cascadeDelete = attribute.isDeleteCascaded();
    boolean viewOnlyDeleteCascaded = cascadeDelete && !entityMetamodel.getManagedType(ExtendedManagedType.class, entityClass).getAttribute(attributeMapping).isDeleteCascaded();
    boolean optimisticLockProtected = attribute.isOptimisticLockProtected();
    Set<Type<?>> readOnlyAllowedSubtypes = attribute.getReadOnlyAllowedSubtypes();
    Set<Type<?>> persistAllowedSubtypes = attribute.getPersistCascadeAllowedSubtypes();
    Set<Type<?>> updateAllowedSubtypes = attribute.getUpdateCascadeAllowedSubtypes();
    JpaProvider jpaProvider = evm.getJpaProvider();
    if (attribute.isSubview()) {
        boolean shouldFlushUpdates = cascadeUpdate && !updateAllowedSubtypes.isEmpty();
        boolean shouldFlushPersists = cascadePersist && !persistAllowedSubtypes.isEmpty();
        ManagedViewTypeImplementor<?> subviewType = (ManagedViewTypeImplementor<?>) ((com.blazebit.persistence.view.metamodel.SingularAttribute<?, ?>) attribute).getType();
        boolean passThrough = false;
        if (attribute.isUpdatable() || shouldFlushUpdates || (passThrough = shouldPassThrough(evm, viewType, attribute))) {
            // TODO: shouldn't this be done for any flat view? or are updatable flat views for entity types disallowed?
            if (!(subviewType.getJpaManagedType() instanceof EntityType<?>)) {
                AttributeAccessor viewAttributeAccessor = Accessors.forViewAttribute(evm, attribute, true);
                // A singular attribute where the subview refers to an embeddable type
                EmbeddableUpdaterBasedViewToEntityMapper viewToEntityMapper = new EmbeddableUpdaterBasedViewToEntityMapper(attributeLocation, evm, subviewType.getJavaType(), readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, subviewType, attribute), shouldFlushPersists, null, owner == null ? this : owner, ownerMapping == null ? attributeMapping : ownerMapping + "." + attributeMapping, localCache);
                CompositeAttributeFlusher nestedFlusher = (CompositeAttributeFlusher) viewToEntityMapper.getFullGraphNode();
                boolean supportsQueryFlush = nestedFlusher.supportsQueryFlush() && jpaProvider.supportsUpdateSetEmbeddable();
                String parameterName;
                String updateFragment;
                if (supportsQueryFlush) {
                    parameterName = attributeName;
                    updateFragment = attributeMapping;
                } else {
                    parameterName = attributeName + "_";
                    updateFragment = attributeMapping + ".";
                }
                return new EmbeddableAttributeFlusher<>(attributeName, attributeMapping, updateFragment, parameterName, optimisticLockProtected, passThrough, supportsQueryFlush, entityAttributeAccessor, viewAttributeAccessor, viewToEntityMapper);
            } else {
                // Subview refers to entity type
                ViewTypeImplementor<?> attributeViewType = (ViewTypeImplementor<?>) subviewType;
                InitialValueAttributeAccessor viewAttributeAccessor = Accessors.forMutableViewAttribute(evm, attribute);
                AttributeAccessor subviewIdAccessor;
                InverseFlusher<Object> inverseFlusher = InverseFlusher.forAttribute(evm, localCache, viewType, attribute, TypeDescriptor.forType(evm, localCache, this, attribute, subviewType, owner, ownerMapping), owner, ownerMapping);
                InverseRemoveStrategy inverseRemoveStrategy = attribute.getInverseRemoveStrategy();
                ManagedType<?> ownerEntityType = owner == null ? viewType.getJpaManagedType() : owner.managedViewType.getJpaManagedType();
                ViewToEntityMapper viewToEntityMapper;
                boolean fetch = shouldFlushUpdates;
                String parameterName = null;
                String attributeElementIdMapping;
                if (ownerEntityType instanceof EntityType<?> && attribute.getMapping() != null) {
                    ExtendedManagedType<?> extendedManagedType = evm.getMetamodel().getEntityMetamodel().getManagedType(ExtendedManagedType.class, attributeViewType.getEntityClass());
                    attributeElementIdMapping = TypeDescriptor.getAttributeElementIdentifier(evm, (EntityType<?>) ownerEntityType, attribute.getName(), ownerMapping, attribute.getMapping(), extendedManagedType.getType());
                } else {
                    attributeElementIdMapping = ((MappingAttribute<?, ?>) attributeViewType.getIdAttribute()).getMapping();
                }
                subviewIdAccessor = Accessors.forSubviewAssociationId(evm, attributeViewType, attributeElementIdMapping, true);
                Attribute<?, ?> attributeIdAttribute = attributeViewType.getJpaManagedType().getAttribute(attributeElementIdMapping);
                javax.persistence.metamodel.Type<?> attributeIdAttributeType = entityMetamodel.type(JpaMetamodelUtils.resolveFieldClass(attributeViewType.getEntityClass(), attributeIdAttribute));
                List<String> idComponentMappings;
                boolean requiresComponentWiseSetInUpdate = true;
                if (requiresComponentWiseSetInUpdate && attributeIdAttributeType instanceof EmbeddableType<?>) {
                    // If the identifier used for the association is an embeddable, we must collect the individual attribute components since updates don't work on embeddables directly
                    Set<Attribute<?, ?>> idAttributeComponents = (Set<Attribute<?, ?>>) ((EmbeddableType<?>) attributeIdAttributeType).getAttributes();
                    idComponentMappings = new ArrayList<>(idAttributeComponents.size());
                    for (Attribute<?, ?> idAttributeComponent : idAttributeComponents) {
                        idComponentMappings.add(attributeMapping + "." + attributeElementIdMapping + "." + idAttributeComponent.getName());
                    }
                } else {
                    idComponentMappings = Collections.singletonList(attributeMapping + "." + attributeElementIdMapping);
                }
                String[] idAttributeMappings = idComponentMappings.toArray(new String[idComponentMappings.size()]);
                if (attribute.isUpdatable() && ownerEntityType instanceof EntityType<?>) {
                    viewToEntityMapper = createViewToEntityMapper(attributeLocation, evm, localCache, (EntityType<?>) ownerEntityType, attributeName, attributeMapping, attributeViewType, cascadePersist, cascadeUpdate, readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, attributeViewType, attribute.getViewTypes(), attributeElementIdMapping), owner, ownerMapping);
                    parameterName = attributeName;
                } else {
                    String elementIdentifier;
                    if (ownerEntityType instanceof EntityType<?>) {
                        elementIdentifier = TypeDescriptor.getAttributeElementIdentifier(evm, (EntityType<?>) ownerEntityType, attributeName, ownerMapping, attributeMapping, attributeViewType.getJpaManagedType());
                    } else {
                        elementIdentifier = null;
                    }
                    AttributeAccessor entityIdAccessor = Accessors.forEntityMapping(evm, attributeViewType.getEntityClass(), elementIdentifier);
                    if (shouldFlushUpdates) {
                        viewToEntityMapper = new UpdaterBasedViewToEntityMapper(attributeLocation, evm, subviewType.getJavaType(), readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, subviewType, attribute), subviewIdAccessor, entityIdAccessor, shouldFlushPersists, owner, ownerMapping, localCache);
                    } else if (!shouldFlushPersists && shouldPassThrough(evm, viewType, attribute)) {
                        viewToEntityMapper = new LoadOnlyViewToEntityMapper(EntityLoaders.referenceLoaderForAttribute(evm, localCache, subviewType, attribute), subviewIdAccessor, entityIdAccessor);
                    } else {
                        viewToEntityMapper = new LoadOrPersistViewToEntityMapper(attributeLocation, evm, subviewType.getJavaType(), readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, subviewType, attribute), subviewIdAccessor, entityIdAccessor, shouldFlushPersists, owner, ownerMapping, localCache);
                    }
                }
                return new SubviewAttributeFlusher<>(attributeName, attributeMapping, optimisticLockProtected, attribute.isUpdatable(), cascadeDelete, attribute.isOrphanRemoval(), viewOnlyDeleteCascaded, subviewType.getConverter(), fetch, idAttributeMappings, parameterName, passThrough, owner != null, entityAttributeAccessor, viewAttributeAccessor, subviewIdAccessor, viewToEntityMapper, inverseFlusher, inverseRemoveStrategy);
            }
        } else {
            return null;
        }
    } else {
        BasicTypeImpl<?> attributeType = (BasicTypeImpl<?>) ((com.blazebit.persistence.view.metamodel.SingularAttribute<?, ?>) attribute).getType();
        TypeDescriptor elementDescriptor = TypeDescriptor.forType(evm, localCache, this, attribute, attributeType, owner, ownerMapping);
        // Basic attributes like String, Integer but also JPA managed types
        boolean updatable = attribute.isUpdatable();
        if (updatable || elementDescriptor.shouldFlushMutations() || shouldPassThrough(evm, viewType, attribute)) {
            // Basic attributes can normally be updated by queries
            InverseFlusher<Object> inverseFlusher = InverseFlusher.forAttribute(evm, localCache, viewType, attribute, elementDescriptor, owner, ownerMapping);
            InverseRemoveStrategy inverseRemoveStrategy = attribute.getInverseRemoveStrategy();
            String parameterName = attributeName;
            String updateFragment = attributeMapping;
            ManagedType<?> ownerEntityType = owner == null ? viewType.getJpaManagedType() : owner.managedViewType.getJpaManagedType();
            UnmappedBasicAttributeCascadeDeleter deleter;
            if (elementDescriptor.isJpaEntity() && cascadeDelete && ownerEntityType instanceof EntityType<?>) {
                String elementIdAttributeName = TypeDescriptor.getAttributeElementIdentifier(evm, (EntityType<?>) ownerEntityType, attributeName, ownerMapping, attributeMapping, attributeType.getManagedType());
                deleter = new UnmappedBasicAttributeCascadeDeleter(evm, attributeName, entityMetamodel.getManagedType(ExtendedManagedType.class, entityClass).getAttribute(attributeMapping), attributeMapping + "." + elementIdAttributeName, false);
            } else {
                deleter = null;
            }
            // When wanting to read the actual value of non-updatable attributes or writing values to attributes we need the view attribute accessor
            // Whenever we merge or persist, we are going to need that
            AttributeAccessor viewAttributeAccessor;
            if (elementDescriptor.shouldFlushMutations()) {
                viewAttributeAccessor = Accessors.forMutableViewAttribute(evm, attribute);
            } else {
                viewAttributeAccessor = Accessors.forViewAttribute(evm, attribute, true);
            }
            Map.Entry<AttributeAccessor, BasicAttributeFlusher>[] componentFlusherEntries = null;
            if (elementDescriptor.isJpaEmbeddable()) {
                if (!jpaProvider.supportsUpdateSetEmbeddable()) {
                    Set<Attribute<?, ?>> attributes = (Set<Attribute<?, ?>>) attributeType.getManagedType().getAttributes();
                    Map<AttributeAccessor, BasicAttributeFlusher> componentFlushers = new HashMap<>(attributes.size());
                    buildComponentFlushers(evm, viewType.getEntityClass(), attributeType.getJavaType(), attributeName + "_", attributeMapping + ".", "", attributes, componentFlushers);
                    componentFlusherEntries = componentFlushers.entrySet().toArray(new Map.Entry[componentFlushers.size()]);
                }
            }
            return new BasicAttributeFlusher<>(attributeName, attributeMapping, true, optimisticLockProtected, updatable, cascadeDelete, attribute.isOrphanRemoval(), viewOnlyDeleteCascaded, componentFlusherEntries, elementDescriptor, updateFragment, parameterName, entityAttributeAccessor, viewAttributeAccessor, deleter, inverseFlusher, inverseRemoveStrategy);
        } else {
            return null;
        }
    }
}
Also used : CompositeAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.CompositeAttributeFlusher) ViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ViewTypeImplementor) ManagedViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) InverseRemoveStrategy(com.blazebit.persistence.view.InverseRemoveStrategy) SubviewAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.SubviewAttributeFlusher) UnmappedBasicAttributeCascadeDeleter(com.blazebit.persistence.view.impl.update.flush.UnmappedBasicAttributeCascadeDeleter) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) EntityType(javax.persistence.metamodel.EntityType) TypeDescriptor(com.blazebit.persistence.view.impl.update.flush.TypeDescriptor) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor) EmbeddableUpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.EmbeddableUpdaterBasedViewToEntityMapper) LoadOrPersistViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper) Set(java.util.Set) HashSet(java.util.HashSet) UpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.UpdaterBasedViewToEntityMapper) EmbeddableUpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.EmbeddableUpdaterBasedViewToEntityMapper) LoadOnlyViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOnlyViewToEntityMapper) MappingAttribute(com.blazebit.persistence.view.metamodel.MappingAttribute) SingularAttribute(javax.persistence.metamodel.SingularAttribute) Attribute(javax.persistence.metamodel.Attribute) AbstractMethodAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) MethodAttribute(com.blazebit.persistence.view.metamodel.MethodAttribute) BasicTypeImpl(com.blazebit.persistence.view.impl.metamodel.BasicTypeImpl) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) EmbeddableAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.EmbeddableAttributeFlusher) LoadOrPersistViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper) LoadOnlyViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOnlyViewToEntityMapper) SimpleMapViewToEntityMapper(com.blazebit.persistence.view.impl.update.flush.SimpleMapViewToEntityMapper) UpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.UpdaterBasedViewToEntityMapper) EmbeddableUpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.EmbeddableUpdaterBasedViewToEntityMapper) MapViewToEntityMapper(com.blazebit.persistence.view.impl.entity.MapViewToEntityMapper) ViewToEntityMapper(com.blazebit.persistence.view.impl.entity.ViewToEntityMapper) JpaProvider(com.blazebit.persistence.spi.JpaProvider) ManagedViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor) ManagedType(javax.persistence.metamodel.ManagedType) BasicType(com.blazebit.persistence.view.metamodel.BasicType) EntityType(javax.persistence.metamodel.EntityType) Type(com.blazebit.persistence.view.metamodel.Type) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) VersionBasicUserType(com.blazebit.persistence.view.spi.type.VersionBasicUserType) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) EmbeddableType(javax.persistence.metamodel.EmbeddableType) ViewType(com.blazebit.persistence.view.metamodel.ViewType) BasicAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.BasicAttributeFlusher) EntityMetamodel(com.blazebit.persistence.parser.EntityMetamodel)

Example 8 with AbstractMethodAttribute

use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.

the class EntityViewUpdaterImpl method createIdFlusher.

public static DirtyAttributeFlusher<?, Object, Object> createIdFlusher(EntityViewManagerImpl evm, Map<Object, EntityViewUpdaterImpl> localCache, ViewType<?> viewType, ViewToEntityMapper viewToEntityMapper, AbstractMethodAttribute<?, ?> idAttribute) {
    String attributeName = idAttribute.getName();
    String attributeMapping = idAttribute.getMapping();
    AttributeAccessor viewAttributeAccessor = Accessors.forViewAttribute(evm, idAttribute, true);
    AttributeAccessor entityAttributeAccessor = Accessors.forEntityMapping(evm, idAttribute);
    CompositeAttributeFlusher nestedFlusher = viewToEntityMapper != null ? (CompositeAttributeFlusher) viewToEntityMapper.getFullGraphNode() : null;
    boolean supportsQueryFlush = nestedFlusher == null || nestedFlusher.supportsQueryFlush() && evm.getJpaProvider().supportsUpdateSetEmbeddable();
    String parameterName;
    String updateFragment;
    if (supportsQueryFlush) {
        parameterName = attributeName;
        updateFragment = attributeMapping;
    } else {
        parameterName = attributeName + "_";
        updateFragment = attributeMapping + ".";
    }
    if (idAttribute.isSubview()) {
        if (viewToEntityMapper == null) {
            return null;
        }
        return new EmbeddableAttributeFlusher<>(attributeName, attributeMapping, updateFragment, parameterName, false, false, supportsQueryFlush, entityAttributeAccessor, viewAttributeAccessor, (EmbeddableUpdaterBasedViewToEntityMapper) viewToEntityMapper);
    } else {
        BasicTypeImpl<?> type = (BasicTypeImpl<?>) ((com.blazebit.persistence.view.metamodel.SingularAttribute<?, ?>) idAttribute).getType();
        // If the id is an embedded id, we need to flush individual components for subviews, so we need to determine the component flushers
        Map.Entry<AttributeAccessor, BasicAttributeFlusher>[] componentFlusherEntries = null;
        if (type.isJpaManaged()) {
            Set<Attribute<?, ?>> attributes = (Set) type.getManagedType().getAttributes();
            Map<AttributeAccessor, BasicAttributeFlusher> componentFlushers = new HashMap<>(attributes.size());
            buildComponentFlushers(evm, viewType.getEntityClass(), type.getJavaType(), attributeName + "_", attributeMapping + ".", "", attributes, componentFlushers);
            componentFlusherEntries = componentFlushers.entrySet().toArray(new Map.Entry[componentFlushers.size()]);
        }
        TypeDescriptor typeDescriptor = TypeDescriptor.forType(evm, localCache, null, idAttribute, type, null, null);
        return new BasicAttributeFlusher<>(attributeName, attributeMapping, true, false, true, false, false, false, componentFlusherEntries, typeDescriptor, updateFragment, parameterName, entityAttributeAccessor, viewAttributeAccessor, null, null, null);
    }
}
Also used : CompositeAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.CompositeAttributeFlusher) Set(java.util.Set) HashSet(java.util.HashSet) MappingAttribute(com.blazebit.persistence.view.metamodel.MappingAttribute) SingularAttribute(javax.persistence.metamodel.SingularAttribute) Attribute(javax.persistence.metamodel.Attribute) AbstractMethodAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) MethodAttribute(com.blazebit.persistence.view.metamodel.MethodAttribute) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) BasicTypeImpl(com.blazebit.persistence.view.impl.metamodel.BasicTypeImpl) TypeDescriptor(com.blazebit.persistence.view.impl.update.flush.TypeDescriptor) EmbeddableAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.EmbeddableAttributeFlusher) BasicAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.BasicAttributeFlusher) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor)

Example 9 with AbstractMethodAttribute

use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.

the class ProxyFactory method createProxyClass.

@SuppressWarnings("unchecked")
private <T> Class<? extends T> createProxyClass(EntityViewManager entityViewManager, ManagedViewTypeImplementor<T> managedViewType, boolean unsafe) {
    ViewType<T> viewType = managedViewType instanceof ViewType<?> ? (ViewType<T>) managedViewType : null;
    Class<?> clazz = managedViewType.getJavaType();
    String suffix = unsafe ? "unsafe_" : "";
    String baseName = clazz.getName();
    String proxyClassName = baseName + "_$$_javassist_entityview_" + suffix;
    CtClass cc = pool.makeClass(proxyClassName);
    CtClass superCc;
    ClassPath classPath = new ClassClassPath(clazz);
    pool.insertClassPath(classPath);
    try {
        addReadsModule(clazz, clazz, ProxyFactory.class);
        superCc = pool.get(getProxyBase(clazz).getName());
        if (clazz.isInterface()) {
            cc.addInterface(superCc);
        } else {
            cc.setSuperclass(superCc);
        }
        boolean dirtyChecking = false;
        CtField dirtyField = null;
        CtField readOnlyParentsField = null;
        CtField parentField = null;
        CtField parentIndexField = null;
        CtField initialStateField = null;
        CtField mutableStateField = null;
        CtMethod markDirtyStub = null;
        long alwaysDirtyMask = 0L;
        cc.addInterface(pool.get(EntityViewProxy.class.getName()));
        addGetJpaManagedClass(cc, managedViewType.getEntityClass());
        addGetJpaManagedBaseClass(cc, getJpaManagedBaseClass(managedViewType));
        addGetEntityViewClass(cc, clazz);
        addIsNewAndReferenceMembers(managedViewType, cc, clazz);
        CtField evmField = new CtField(pool.get(EntityViewManager.class.getName()), SerializableEntityViewManager.EVM_FIELD_NAME, cc);
        evmField.setModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.VOLATILE);
        cc.addField(evmField);
        cc.addField(CtField.make("public static final " + EntityViewManager.class.getName() + " " + SerializableEntityViewManager.SERIALIZABLE_EVM_FIELD_NAME + " = new " + SerializableEntityViewManager.class.getName() + "(" + cc.getName() + ".class, " + cc.getName() + "#" + SerializableEntityViewManager.EVM_FIELD_NAME + ");", cc));
        if (managedViewType.isUpdatable() || managedViewType.isCreatable()) {
            if (true || managedViewType.getFlushMode() == FlushMode.LAZY || managedViewType.getFlushMode() == FlushMode.PARTIAL) {
                cc.addInterface(pool.get(DirtyStateTrackable.class.getName()));
                initialStateField = new CtField(pool.get(Object[].class.getName()), "$$_initialState", cc);
                initialStateField.setModifiers(getModifiers(false));
                cc.addField(initialStateField);
                addGetter(cc, initialStateField, "$$_getInitialState");
            }
            cc.addInterface(pool.get(MutableStateTrackable.class.getName()));
            cc.addInterface(pool.get(DirtyTracker.class.getName()));
            mutableStateField = new CtField(pool.get(Object[].class.getName()), "$$_mutableState", cc);
            mutableStateField.setModifiers(getModifiers(false));
            cc.addField(mutableStateField);
            CtField initializedField = new CtField(CtClass.booleanType, "$$_initialized", cc);
            initializedField.setModifiers(getModifiers(false));
            cc.addField(initializedField);
            readOnlyParentsField = new CtField(pool.get(List.class.getName()), "$$_readOnlyParents", cc);
            readOnlyParentsField.setModifiers(getModifiers(true));
            readOnlyParentsField.setGenericSignature(Descriptor.of(List.class.getName()) + "<" + Descriptor.of(Object.class.getName()) + ">;");
            cc.addField(readOnlyParentsField);
            parentField = new CtField(pool.get(DirtyTracker.class.getName()), "$$_parent", cc);
            parentField.setModifiers(getModifiers(true));
            cc.addField(parentField);
            parentIndexField = new CtField(CtClass.intType, "$$_parentIndex", cc);
            parentIndexField.setModifiers(getModifiers(true));
            cc.addField(parentIndexField);
            dirtyChecking = true;
            addGetter(cc, mutableStateField, "$$_getMutableState");
            addGetter(cc, readOnlyParentsField, "$$_getReadOnlyParents");
            addGetter(cc, parentField, "$$_getParent");
            addGetter(cc, parentIndexField, "$$_getParentIndex");
            addAddReadOnlyParent(cc, readOnlyParentsField, parentField);
            addRemoveReadOnlyParent(cc, readOnlyParentsField);
            addSetParent(cc, parentField, parentIndexField);
            addHasParent(cc, parentField);
            addUnsetParent(cc, parentField, parentIndexField, readOnlyParentsField);
            markDirtyStub = addMarkDirtyStub(cc);
        }
        Set<MethodAttribute<? super T, ?>> attributes = new LinkedHashSet<>(managedViewType.getAttributes());
        CtField[] attributeFields = new CtField[attributes.size()];
        CtClass[] attributeTypes = new CtClass[attributes.size()];
        Map<String, CtField> fieldMap = new HashMap<>(attributes.size());
        int i = 0;
        // Create the id field
        AbstractMethodAttribute<? super T, ?> idAttribute = null;
        CtField idField = null;
        AbstractMethodAttribute<? super T, ?> versionAttribute = null;
        final AbstractMethodAttribute<?, ?>[] methodAttributes = new AbstractMethodAttribute[attributeFields.length];
        if (viewType != null) {
            idAttribute = (AbstractMethodAttribute<? super T, ?>) viewType.getIdAttribute();
            versionAttribute = (AbstractMethodAttribute<? super T, ?>) viewType.getVersionAttribute();
            idField = addMembersForAttribute(idAttribute, clazz, cc, null, false, true, mutableStateField != null);
            fieldMap.put(idAttribute.getName(), idField);
            attributeFields[0] = idField;
            attributeTypes[0] = idField.getType();
            methodAttributes[0] = idAttribute;
            attributes.remove(idAttribute);
            i = 1;
            if (mutableStateField != null) {
                addSetId(cc, idField);
            }
        } else if (mutableStateField != null) {
            addSetId(cc, null);
        }
        addGetter(cc, idField, "$$_getId", Object.class);
        int mutableAttributeCount = 0;
        for (MethodAttribute<?, ?> attribute : attributes) {
            AbstractMethodAttribute<?, ?> methodAttribute = (AbstractMethodAttribute<?, ?>) attribute;
            if (NEEDS_READS_INJECTOR) {
                for (Class<?> allowedSubtype : attribute.getAllowedSubtypes()) {
                    addReadsModule(clazz, clazz, allowedSubtype);
                }
                for (Type<?> allowedSubtype : attribute.getReadOnlyAllowedSubtypes()) {
                    addReadsModule(clazz, clazz, allowedSubtype.getJavaType());
                }
                for (Type<?> allowedSubtype : attribute.getPersistCascadeAllowedSubtypes()) {
                    addReadsModule(clazz, clazz, allowedSubtype.getJavaType());
                }
                for (Type<?> allowedSubtype : attribute.getUpdateCascadeAllowedSubtypes()) {
                    addReadsModule(clazz, clazz, allowedSubtype.getJavaType());
                }
            }
            boolean forceMutable = mutableStateField != null && methodAttribute == versionAttribute;
            CtField attributeField = addMembersForAttribute(methodAttribute, clazz, cc, mutableStateField, dirtyChecking, false, forceMutable);
            fieldMap.put(attribute.getName(), attributeField);
            attributeFields[i] = attributeField;
            attributeTypes[i] = attributeField.getType();
            methodAttributes[i] = methodAttribute;
            if (methodAttribute.hasDirtyStateIndex()) {
                mutableAttributeCount++;
            }
            i++;
        }
        if (mutableStateField != null) {
            if (versionAttribute != null) {
                CtField versionField = fieldMap.get(versionAttribute.getName());
                addGetter(cc, versionField, "$$_getVersion", Object.class);
                addSetVersion(cc, versionField);
            } else {
                addGetter(cc, null, "$$_getVersion", Object.class);
                addSetVersion(cc, null);
            }
        } else {
            addGetter(cc, null, "$$_getVersion", Object.class);
        }
        if (dirtyChecking) {
            addReplaceAttribute(cc, methodAttributes);
            cc.removeMethod(markDirtyStub);
            if (mutableAttributeCount > 64) {
                throw new IllegalArgumentException("Support for more than 64 mutable attributes per view is not yet implemented! " + viewType.getJavaType().getName() + " has " + mutableAttributeCount);
            } else {
                dirtyField = new CtField(CtClass.longType, "$$_dirty", cc);
                dirtyField.setModifiers(getModifiers(true));
                cc.addField(dirtyField);
                boolean allSupportDirtyTracking = true;
                boolean[] supportsDirtyTracking = new boolean[mutableAttributeCount];
                int mutableAttributeIndex = 0;
                for (int j = 0; j < methodAttributes.length; j++) {
                    if (methodAttributes[j] != null && methodAttributes[j].hasDirtyStateIndex()) {
                        if (supportsDirtyTracking(methodAttributes[j])) {
                            supportsDirtyTracking[mutableAttributeIndex++] = true;
                        } else {
                            allSupportDirtyTracking = false;
                            alwaysDirtyMask |= 1 << mutableAttributeIndex;
                            supportsDirtyTracking[mutableAttributeIndex++] = false;
                        }
                    }
                }
                addIsDirty(cc, dirtyField, allSupportDirtyTracking);
                addIsDirtyAttribute(cc, dirtyField, supportsDirtyTracking, allSupportDirtyTracking);
                addMarkDirty(cc, dirtyField);
                addUnmarkDirty(cc, dirtyField, alwaysDirtyMask);
                addSetDirty(cc, dirtyField, alwaysDirtyMask);
                addResetDirty(cc, dirtyField, alwaysDirtyMask);
                addGetDirty(cc, dirtyField);
                addGetSimpleDirty(cc, dirtyField);
                addCopyDirty(cc, dirtyField, supportsDirtyTracking, allSupportDirtyTracking);
            }
        }
        createEqualsHashCodeMethods(viewType, managedViewType, cc, superCc, attributeFields, idField);
        cc.addMethod(createToString(managedViewType, cc, viewType != null, attributeFields));
        createSpecialMethods(managedViewType, cc, cc);
        createSerializationSubclass(managedViewType, cc);
        Set<MappingConstructorImpl<T>> constructors = (Set<MappingConstructorImpl<T>>) (Set<?>) managedViewType.getConstructors();
        boolean hasEmptyConstructor = managedViewType.hasEmptyConstructor();
        if (hasEmptyConstructor) {
            // Create constructor for create models
            cc.addConstructor(createCreateConstructor(entityViewManager, managedViewType, cc, attributeFields, attributeTypes, idField, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, alwaysDirtyMask, unsafe));
        }
        boolean addedReferenceConstructor = false;
        if (idField != null && hasEmptyConstructor) {
            // Id only constructor for reference models
            cc.addConstructor(createReferenceConstructor(entityViewManager, managedViewType, cc, attributeFields, idField, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, alwaysDirtyMask, unsafe));
            addedReferenceConstructor = true;
        }
        if (shouldAddDefaultConstructor(hasEmptyConstructor, addedReferenceConstructor, attributeFields)) {
            cc.addConstructor(createNormalConstructor(entityViewManager, managedViewType, null, cc, attributeFields, attributeTypes, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, alwaysDirtyMask, unsafe));
            cc.addConstructor(createTupleConstructor(managedViewType, null, cc, attributeFields.length, attributeFields.length, attributeFields, attributeTypes, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, false, alwaysDirtyMask, unsafe));
            cc.addConstructor(createTupleConstructor(managedViewType, null, cc, attributeFields.length, attributeFields.length, attributeFields, attributeTypes, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, true, alwaysDirtyMask, unsafe));
        } else if (hasEmptyConstructor) {
            cc.addConstructor(createTupleConstructor(managedViewType, null, cc, attributeFields.length, attributeFields.length, attributeFields, attributeTypes, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, false, alwaysDirtyMask, unsafe));
            cc.addConstructor(createTupleConstructor(managedViewType, null, cc, attributeFields.length, attributeFields.length, attributeFields, attributeTypes, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, true, alwaysDirtyMask, unsafe));
        }
        for (MappingConstructorImpl<?> constructor : constructors) {
            int constructorParameterCount = attributeFields.length + constructor.getParameterAttributes().size();
            // Skip the empty constructor which was handled before
            if (constructor.getParameterAttributes().size() == 0) {
                continue;
            }
            CtClass[] constructorAttributeTypes = new CtClass[constructorParameterCount];
            System.arraycopy(attributeTypes, 0, constructorAttributeTypes, 0, attributeFields.length);
            // Append super constructor parameters to default constructor parameters
            CtConstructor superConstructor = findConstructor(superCc, constructor);
            System.arraycopy(superConstructor.getParameterTypes(), 0, constructorAttributeTypes, attributeFields.length, superConstructor.getParameterTypes().length);
            cc.addConstructor(createNormalConstructor(entityViewManager, managedViewType, constructor, cc, attributeFields, constructorAttributeTypes, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, alwaysDirtyMask, unsafe));
            cc.addConstructor(createTupleConstructor(managedViewType, constructor, cc, attributeFields.length, constructorAttributeTypes.length, attributeFields, constructorAttributeTypes, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, false, alwaysDirtyMask, unsafe));
            cc.addConstructor(createTupleConstructor(managedViewType, constructor, cc, attributeFields.length, constructorAttributeTypes.length, attributeFields, constructorAttributeTypes, initialStateField, mutableStateField, methodAttributes, mutableAttributeCount, true, alwaysDirtyMask, unsafe));
        }
        return defineOrGetClass(entityViewManager, unsafe, clazz, clazz, cc);
    } catch (Exception ex) {
        throw new RuntimeException("Probably we did something wrong, please contact us if you see this message.", ex);
    } finally {
        pool.removeClassPath(classPath);
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ClassClassPath(javassist.ClassClassPath) ClassPath(javassist.ClassPath) RecordingNavigableSet(com.blazebit.persistence.view.impl.collection.RecordingNavigableSet) Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) RecordingSet(com.blazebit.persistence.view.impl.collection.RecordingSet) LinkedHashMap(java.util.LinkedHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) AbstractMethodAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute) MethodAttribute(com.blazebit.persistence.view.metamodel.MethodAttribute) CtField(javassist.CtField) ArrayList(java.util.ArrayList) List(java.util.List) RecordingList(com.blazebit.persistence.view.impl.collection.RecordingList) DirtyTracker(com.blazebit.persistence.view.spi.type.DirtyTracker) BasicDirtyTracker(com.blazebit.persistence.view.spi.type.BasicDirtyTracker) InvocationTargetException(java.lang.reflect.InvocationTargetException) IOException(java.io.IOException) NotFoundException(javassist.NotFoundException) CannotCompileException(javassist.CannotCompileException) CtConstructor(javassist.CtConstructor) CtClass(javassist.CtClass) AbstractMethodAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute) ClassClassPath(javassist.ClassClassPath) MappingConstructorImpl(com.blazebit.persistence.view.impl.metamodel.MappingConstructorImpl) CtMethod(javassist.CtMethod)

Example 10 with AbstractMethodAttribute

use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.

the class ViewTypeObjectBuilderTemplate method addViewRootMappingIfNeeded.

private int addViewRootMappingIfNeeded(TupleElementMapperBuilder mapperBuilder, Set<Feature> features, String subviewAliasPrefix, String attributePath, int viewRootIndex) {
    if (viewRoot.getJpaManagedType() instanceof EntityType<?>) {
        boolean viewRootMapping = false;
        if (viewRoot instanceof ViewType<?>) {
            MethodAttribute idAttribute = ((ViewType) viewRoot).getIdAttribute();
            if (idAttribute.isSubview() || !((AbstractMethodAttribute) idAttribute).isUpdateMappable()) {
                viewRootMapping = true;
            }
        } else {
            viewRootMapping = true;
        }
        if (viewRootMapping) {
            features.add(Feature.SUBQUERY_CORRELATION);
            viewRootIndex = tupleOffset + mapperBuilder.mapperIndex();
            javax.persistence.metamodel.SingularAttribute<?, ?> singleIdAttribute = JpaMetamodelUtils.getSingleIdAttribute((IdentifiableType<?>) viewRoot.getJpaManagedType());
            mapperBuilder.addMapper(createMapper((BasicUserTypeStringSupport<?>) null, singleIdAttribute.getName(), subviewAliasPrefix + "_view_root_id", attributePath, null, null, EMPTY));
        }
    }
    return viewRootIndex;
}
Also used : EntityType(javax.persistence.metamodel.EntityType) AbstractMethodAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute) MethodAttribute(com.blazebit.persistence.view.metamodel.MethodAttribute) BasicUserTypeStringSupport(com.blazebit.persistence.view.spi.type.BasicUserTypeStringSupport) AbstractMethodAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ViewType(com.blazebit.persistence.view.metamodel.ViewType)

Aggregations

AbstractMethodAttribute (com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute)10 MethodAttribute (com.blazebit.persistence.view.metamodel.MethodAttribute)6 Set (java.util.Set)5 ManagedViewType (com.blazebit.persistence.view.metamodel.ManagedViewType)4 ViewType (com.blazebit.persistence.view.metamodel.ViewType)4 EntityType (javax.persistence.metamodel.EntityType)4 ExtendedAttribute (com.blazebit.persistence.spi.ExtendedAttribute)3 AttributeAccessor (com.blazebit.persistence.view.impl.accessor.AttributeAccessor)3 InitialValueAttributeAccessor (com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor)3 BasicAttributeFlusher (com.blazebit.persistence.view.impl.update.flush.BasicAttributeFlusher)3 EmbeddableAttributeFlusher (com.blazebit.persistence.view.impl.update.flush.EmbeddableAttributeFlusher)3 TypeDescriptor (com.blazebit.persistence.view.impl.update.flush.TypeDescriptor)3 MapAttribute (com.blazebit.persistence.view.metamodel.MapAttribute)3 MappingAttribute (com.blazebit.persistence.view.metamodel.MappingAttribute)3 PluralAttribute (com.blazebit.persistence.view.metamodel.PluralAttribute)3 HashMap (java.util.HashMap)3 LinkedHashMap (java.util.LinkedHashMap)3 EntityMetamodel (com.blazebit.persistence.parser.EntityMetamodel)2 ExtendedManagedType (com.blazebit.persistence.spi.ExtendedManagedType)2 RecordingList (com.blazebit.persistence.view.impl.collection.RecordingList)2