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);
}
}
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;
}
}
}
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);
}
}
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);
}
}
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;
}
Aggregations