use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.
the class EntityViewUpdaterImpl method createPluralAttributeSubFlusher.
private DirtyAttributeFlusher<?, ?, ?> createPluralAttributeSubFlusher(EntityViewManagerImpl evm, Map<Object, EntityViewUpdaterImpl> localCache, ManagedViewTypeImplementor<?> viewType, AbstractMethodAttribute<?, ?> attribute, String name, Type<?> type, EntityViewUpdaterImpl owner, String ownerMapping) {
EntityMetamodel entityMetamodel = evm.getMetamodel().getEntityMetamodel();
String attributeName = attribute.getName() + "_" + name;
String attributeMapping = attribute.getMapping();
String attributeLocation = attribute.getLocation();
Set<Type<?>> readOnlyAllowedSubtypes = attribute.getReadOnlyAllowedSubtypes();
Set<Type<?>> persistAllowedSubtypes = attribute.getPersistCascadeAllowedSubtypes();
Set<Type<?>> updateAllowedSubtypes = attribute.getUpdateCascadeAllowedSubtypes();
if (type instanceof ManagedViewType<?>) {
ManagedViewTypeImplementor<?> subviewType = (ManagedViewTypeImplementor<?>) type;
if (!(subviewType.getJpaManagedType() instanceof EntityType<?>)) {
// 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), false, null, owner, ownerMapping == null ? attributeMapping : ownerMapping + "." + attributeMapping, localCache);
String parameterName = attributeName + "_";
String updateFragment = attributeMapping + ".";
return new EmbeddableAttributeFlusher<>(attributeName, attributeMapping, updateFragment, parameterName, false, false, false, null, null, viewToEntityMapper);
} else {
ViewTypeImplementor<?> attributeViewType = (ViewTypeImplementor<?>) subviewType;
InitialValueAttributeAccessor viewAttributeAccessor = Accessors.forMutableViewAttribute(evm, attribute);
AttributeAccessor subviewIdAccessor;
ManagedType<?> ownerManagedType = owner == null ? viewType.getJpaManagedType() : owner.managedViewType.getJpaManagedType();
EntityType<?> ownerEntityType = ownerManagedType instanceof EntityType<?> ? (EntityType<?>) ownerManagedType : null;
String attributeElementIdMapping;
if (ownerEntityType != null && attribute.getMapping() != null) {
ExtendedManagedType<?> extendedManagedType = evm.getMetamodel().getEntityMetamodel().getManagedType(ExtendedManagedType.class, attributeViewType.getEntityClass());
attributeElementIdMapping = TypeDescriptor.getAttributeElementIdentifier(evm, 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);
}
} else {
idComponentMappings = Collections.singletonList(attributeMapping + "." + attributeElementIdMapping);
}
String[] idAttributeMappings = idComponentMappings.toArray(new String[idComponentMappings.size()]);
ViewToEntityMapper viewToEntityMapper = createViewToEntityMapper(attributeLocation, evm, localCache, ownerEntityType, attributeName, attributeMapping, attributeViewType, false, false, readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, attributeViewType, attribute.getViewTypes(), attributeElementIdMapping), owner, ownerMapping);
String parameterName = attributeName;
return new SubviewAttributeFlusher<>(attributeName, attributeMapping, false, true, false, false, false, subviewType.getConverter(), false, idAttributeMappings, parameterName, false, owner != null, null, viewAttributeAccessor, subviewIdAccessor, viewToEntityMapper, null, null);
}
} else {
TypeDescriptor elementDescriptor = TypeDescriptor.forType(evm, localCache, this, attribute, type, owner, ownerMapping);
String parameterName = attributeName;
String updateFragment = attributeMapping;
// TODO: Why?
boolean supportsQueryFlush = !elementDescriptor.isJpaEmbeddable();
return new BasicAttributeFlusher<>(attributeName, attributeMapping, supportsQueryFlush, false, true, false, false, false, null, elementDescriptor, updateFragment, parameterName, null, null, null, null, null);
}
}
use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.
the class ViewTypeObjectBuilderTemplate method addEmbeddingViewMappingIfNeeded.
private int addEmbeddingViewMappingIfNeeded(TupleElementMapperBuilder mapperBuilder, Set<Feature> features, String subviewAliasPrefix, String attributePath, int embeddingViewIndex) {
if (viewType.getJpaManagedType() instanceof EntityType<?>) {
boolean embeddingViewMapping = false;
if (viewType instanceof ViewType<?>) {
MethodAttribute idAttribute = ((ViewType) viewType).getIdAttribute();
if (idAttribute.isSubview() || !((AbstractMethodAttribute) idAttribute).isUpdateMappable()) {
embeddingViewMapping = true;
}
} else {
embeddingViewMapping = true;
}
if (embeddingViewMapping) {
embeddingViewIndex = tupleOffset + mapperBuilder.mapperIndex();
javax.persistence.metamodel.SingularAttribute<?, ?> singleIdAttribute = JpaMetamodelUtils.getSingleIdAttribute((IdentifiableType<?>) viewType.getJpaManagedType());
mapperBuilder.addMapper(createMapper((BasicUserTypeStringSupport<?>) null, singleIdAttribute.getName(), subviewAliasPrefix + "_embedding_view_id", attributePath, null, null, EMPTY));
}
}
return embeddingViewIndex;
}
use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.
the class EntityViewSettingHelper method applyAttributeSorters.
private static <T, Q extends FullQueryBuilder<T, Q>> void applyAttributeSorters(EntityViewSetting<?, ?> setting, Q cb, String viewRoot, Set<String> fetches, ManagedViewTypeImplementor<?> entityViewRoot) {
String name = entityViewRoot.getJavaType().getSimpleName();
StringBuilder sb = null;
for (Map.Entry<String, Sorter> attributeSorterEntry : setting.getAttributeSorters().entrySet()) {
String attributeName = attributeSorterEntry.getKey();
NavigableMap<String, AbstractMethodAttribute<?, ?>> recursiveAttributes = (NavigableMap<String, AbstractMethodAttribute<?, ?>>) entityViewRoot.getRecursiveAttributes();
Map.Entry<String, AbstractMethodAttribute<?, ?>> entry = recursiveAttributes.floorEntry(attributeName);
if (entry == null || !attributeName.startsWith(entry.getKey())) {
throw new IllegalArgumentException("The attribute with the name '" + attributeName + "' couldn't be found on the view type '" + name + "'");
}
if (attributeName.length() != entry.getKey().length()) {
throw new UnsupportedOperationException("No support yet for entity attribute filtering!");
// // If we get here, the attribute type is a managed type and we can copy the rest of the parts
// for (; i < parts.length; i++) {
// type = jpaMetamodel.managedType(maybeUnmanagedType);
// newSb.append('.');
// newSb.append(parts[i]);
// jpaAttribute = type.getAttribute(parts[i]);
// maybeUnmanagedType = jpaAttribute.getJavaType();
// }
}
Sorter sorter = attributeSorterEntry.getValue();
if (sb == null) {
sb = new StringBuilder(name.length() + attributeName.length() + 1);
} else {
sb.setLength(0);
}
String attributeExpression;
if (fetches.isEmpty() || fetches.contains(attributeName)) {
attributeExpression = buildAlias(sb, name, attributeName);
} else {
attributeExpression = buildMapping(sb, cb, viewRoot, recursiveAttributes, attributeName);
}
sorter.apply(cb, attributeExpression);
}
}
use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.
the class ProxyFactory method addReplaceAttribute.
private CtMethod addReplaceAttribute(CtClass cc, AbstractMethodAttribute[] attributes) throws CannotCompileException {
String desc = "(" + Descriptor.of(Object.class.getName()) + "I" + Descriptor.of(Object.class.getName()) + ")V";
ConstPool cp = cc.getClassFile().getConstPool();
MethodInfo minfo = new MethodInfo(cp, "$$_replaceAttribute", desc);
minfo.setAccessFlags(AccessFlag.PUBLIC);
StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append("\tswitch ($2) {");
for (int i = 0; i < attributes.length; i++) {
AbstractMethodAttribute attribute = attributes[i];
if (attribute != null && attribute.hasDirtyStateIndex()) {
sb.append("\t\tcase ").append(attribute.getDirtyStateIndex()).append(": ");
// If there is no setter, we simply ignore the object rather than throwing an exception
if (ReflectionUtils.getSetter(attribute.getDeclaringType().getJavaType(), attribute.getName()) != null) {
sb.append("$0.set").append(Character.toUpperCase(attribute.getName().charAt(0))).append(attribute.getName(), 1, attribute.getName().length());
sb.append('(');
if (attribute.getConvertedJavaType().isPrimitive()) {
appendUnwrap(sb, attribute.getConvertedJavaType(), "$3");
} else {
sb.append("(").append(attribute.getConvertedJavaType().getCanonicalName()).append(") $3");
}
sb.append("); ");
}
sb.append("break;\n");
}
}
sb.append("\t\tdefault: throw new IllegalArgumentException(\"Invalid non-mutable attribute index: \" + $2);\n");
sb.append("\t}\n");
sb.append('}');
CtMethod method = CtMethod.make(minfo, cc);
method.setBody(sb.toString());
cc.addMethod(method);
return method;
}
use of com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute in project blaze-persistence by Blazebit.
the class ProxyFactory method createSerializationSubclass.
private void createSerializationSubclass(ManagedViewTypeImplementor<?> managedViewType, CtClass cc) throws Exception {
boolean hasSelfConstructor = false;
OUTER: for (MappingConstructor<?> constructor : managedViewType.getConstructors()) {
for (ParameterAttribute<?, ?> parameterAttribute : constructor.getParameterAttributes()) {
if (parameterAttribute.isSelfParameter()) {
hasSelfConstructor = true;
break OUTER;
}
}
}
if (hasSelfConstructor) {
String serializableClassName = cc.getName() + "Ser";
Set<AbstractMethodAttribute<?, ?>> attributes = (Set<AbstractMethodAttribute<?, ?>>) (Set<?>) managedViewType.getAttributes();
CtClass[] attributeTypes = new CtClass[attributes.size()];
createSerializableClass(managedViewType, cc, serializableClassName, attributes, attributeTypes);
ConstPool cp = cc.getClassFile().getConstPool();
MethodInfo minfo = new MethodInfo(cp, "createSelf", Descriptor.ofMethod(pool.get(managedViewType.getJavaType().getName()), attributeTypes));
CtMethod method = CtMethod.make(minfo, cc);
minfo.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC);
StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append("\t").append(serializableClassName).append(" self = (").append(serializableClassName).append(") new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(");
sb.append(serializableClassName).append(".EMPTY_INSTANCE_BYTES)).readObject();\n");
int index = 1;
for (MethodAttribute<?, ?> attribute : attributes) {
sb.append("\tself.").append(attribute.getName()).append(" = $").append(index).append(";\n");
index++;
}
sb.append("\treturn self;\n");
sb.append("}");
method.setBody(sb.toString());
cc.addMethod(method);
}
}
Aggregations