use of io.requery.util.ObservableCollection in project requery by requery.
the class EntityWriter method updateAssociation.
@SuppressWarnings("unchecked")
private void updateAssociation(Cascade mode, E entity, EntityProxy<E> proxy, Attribute<E, ?> attribute) {
switch(attribute.getCardinality()) {
case ONE_TO_ONE:
S value = (S) proxy.get(attribute, false);
if (value != null) {
Attribute<S, Object> mapped = Attributes.get(attribute.getMappedAttribute());
EntityProxy<S> referred = context.proxyOf(value, true);
referred.set(mapped, entity, PropertyState.MODIFIED);
cascadeWrite(mode, value, referred);
} else if (!stateless) {
throw new PersistenceException("1-1 relationship can only be removed from the owning side");
}
break;
case ONE_TO_MANY:
Object relation = proxy.get(attribute, false);
if (relation instanceof ObservableCollection) {
ObservableCollection<S> collection = (ObservableCollection<S>) relation;
CollectionChanges<?, S> changes = (CollectionChanges<?, S>) collection.observer();
List<S> added = new ArrayList<>(changes.addedElements());
List<S> removed = new ArrayList<>(changes.removedElements());
changes.clear();
for (S element : added) {
updateMappedAssociation(mode, element, attribute, entity);
}
for (S element : removed) {
updateMappedAssociation(Cascade.UPDATE, element, attribute, null);
}
} else if (relation instanceof Iterable) {
Iterable<S> iterable = (Iterable<S>) relation;
for (S added : iterable) {
updateMappedAssociation(mode, added, attribute, entity);
}
} else {
throw new IllegalStateException("unsupported relation type " + relation);
}
break;
case MANY_TO_MANY:
final Class referencedClass = attribute.getReferencedClass();
if (referencedClass == null) {
throw new IllegalStateException("Invalid referenced class in " + attribute);
}
Type<?> referencedType = model.typeOf(referencedClass);
QueryAttribute<S, Object> tKey = null;
QueryAttribute<S, Object> uKey = null;
for (Attribute a : referencedType.getAttributes()) {
Class<?> referenced = a.getReferencedClass();
if (referenced != null) {
if (tKey == null && entityClass.isAssignableFrom(referenced)) {
tKey = Attributes.query(a);
} else if (attribute.getElementClass() != null && attribute.getElementClass().isAssignableFrom(referenced)) {
uKey = Attributes.query(a);
}
}
}
Objects.requireNotNull(tKey);
Objects.requireNotNull(uKey);
Attribute<E, Object> tRef = Attributes.get(tKey.getReferencedAttribute());
Attribute<S, Object> uRef = Attributes.get(uKey.getReferencedAttribute());
CollectionChanges<?, S> changes = null;
relation = proxy.get(attribute, false);
Iterable<S> addedElements = (Iterable<S>) relation;
boolean isObservable = relation instanceof ObservableCollection;
if (relation instanceof ObservableCollection) {
ObservableCollection<S> collection = (ObservableCollection<S>) relation;
changes = (CollectionChanges<?, S>) collection.observer();
if (changes != null) {
addedElements = changes.addedElements();
}
}
for (S added : addedElements) {
S junction = (S) referencedType.getFactory().get();
EntityProxy<S> junctionProxy = context.proxyOf(junction, false);
EntityProxy<S> uProxy = context.proxyOf(added, false);
if (attribute.getCascadeActions().contains(CascadeAction.SAVE)) {
cascadeWrite(mode, added, uProxy);
}
Object tValue = proxy.get(tRef, false);
Object uValue = uProxy.get(uRef, false);
junctionProxy.set(tKey, tValue, PropertyState.MODIFIED);
junctionProxy.set(uKey, uValue, PropertyState.MODIFIED);
Cascade cascade = isObservable && mode == Cascade.UPSERT ? Cascade.UPSERT : Cascade.INSERT;
cascadeWrite(cascade, junction, null);
}
if (changes != null) {
Object keyValue = proxy.get(tRef, false);
for (S removed : changes.removedElements()) {
Object otherValue = context.proxyOf(removed, false).get(uRef);
Class<? extends S> removeType = (Class<? extends S>) referencedType.getClassType();
Supplier<? extends Scalar<Integer>> query = queryable.delete(removeType).where(tKey.equal(keyValue)).and(uKey.equal(otherValue));
int count = query.get().value();
if (count != 1) {
throw new RowCountException(1, count);
}
}
changes.clear();
}
break;
case MANY_TO_ONE:
default:
break;
}
context.read(type.getClassType()).refresh(entity, proxy, attribute);
}
Aggregations