Object oldProperty = null;
try {
oldProperty = accessorFactory.createPropertyAccessor(propertyName,
componentDescriptor.getComponentContract()).getValue(proxy);
} catch (IllegalAccessException ex) {
throw new ComponentException(ex);
} catch (InvocationTargetException ex) {
if (ex.getCause() instanceof RuntimeException) {
throw (RuntimeException) ex.getCause();
}
throw new ComponentException(ex.getCause());
} catch (NoSuchMethodException ex) {
throw new ComponentException(ex);
}
Object actualNewProperty;
if (propertyProcessorsEnabled) {
actualNewProperty = propertyDescriptor
.interceptSetter(proxy, newProperty);
} else {
actualNewProperty = newProperty;
}
if (ObjectUtils.equals(oldProperty, actualNewProperty)) {
return;
}
if (propertyProcessorsEnabled) {
propertyDescriptor.preprocessSetter(proxy, actualNewProperty);
}
if (propertyDescriptor instanceof IRelationshipEndPropertyDescriptor) {
// It's a relation end
IRelationshipEndPropertyDescriptor reversePropertyDescriptor = ((IRelationshipEndPropertyDescriptor) propertyDescriptor)
.getReverseRelationEnd();
try {
if (propertyDescriptor instanceof IReferencePropertyDescriptor) {
// It's a 'one' relation end
storeReferenceProperty(
(IReferencePropertyDescriptor<?>) propertyDescriptor,
oldProperty, actualNewProperty);
if (reversePropertyDescriptor != null) {
// It is bidirectionnal, so we are going to update the other end.
if (reversePropertyDescriptor instanceof IReferencePropertyDescriptor) {
// It's a one-to-one relationship
if (oldProperty instanceof IEntity) {
entityDetached((IEntity) oldProperty);
}
IAccessor reversePropertyAccessor = accessorFactory
.createPropertyAccessor(reversePropertyDescriptor.getName(),
((IReferencePropertyDescriptor<?>) propertyDescriptor)
.getReferencedDescriptor().getComponentContract());
if (oldProperty != null) {
reversePropertyAccessor.setValue(oldProperty, null);
}
if (actualNewProperty != null) {
reversePropertyAccessor.setValue(actualNewProperty, proxy);
}
} else if (reversePropertyDescriptor instanceof ICollectionPropertyDescriptor) {
// It's a one-to-many relationship
ICollectionAccessor reversePropertyAccessor = accessorFactory
.createCollectionPropertyAccessor(
reversePropertyDescriptor.getName(),
((IReferencePropertyDescriptor<?>) propertyDescriptor)
.getReferencedDescriptor().getComponentContract(),
((ICollectionPropertyDescriptor<?>) reversePropertyDescriptor)
.getCollectionDescriptor().getElementDescriptor()
.getComponentContract());
if (reversePropertyAccessor instanceof IModelDescriptorAware) {
((IModelDescriptorAware) reversePropertyAccessor)
.setModelDescriptor(reversePropertyDescriptor);
}
if (oldProperty != null) {
reversePropertyAccessor.removeFromValue(oldProperty, proxy);
}
if (actualNewProperty != null) {
reversePropertyAccessor.addToValue(actualNewProperty, proxy);
}
}
}
} else if (propertyDescriptor instanceof ICollectionPropertyDescriptor) {
// It's a 'many' relation end
Collection<Object> oldPropertyElementsToRemove = new HashSet<Object>();
Collection<Object> newPropertyElementsToAdd = new HashSet<Object>();
Collection<Object> propertyElementsToKeep = new HashSet<Object>();
if (oldProperty != null) {
oldPropertyElementsToRemove.addAll((Collection<?>) oldProperty);
propertyElementsToKeep.addAll((Collection<?>) oldProperty);
}
if (actualNewProperty != null) {
newPropertyElementsToAdd.addAll((Collection<?>) actualNewProperty);
}
propertyElementsToKeep.retainAll(newPropertyElementsToAdd);
oldPropertyElementsToRemove.removeAll(propertyElementsToKeep);
newPropertyElementsToAdd.removeAll(propertyElementsToKeep);
ICollectionAccessor propertyAccessor = accessorFactory
.createCollectionPropertyAccessor(propertyDescriptor.getName(),
componentDescriptor.getComponentContract(),
((ICollectionPropertyDescriptor<?>) propertyDescriptor)
.getCollectionDescriptor().getElementDescriptor()
.getComponentContract());
for (Object element : oldPropertyElementsToRemove) {
propertyAccessor.removeFromValue(proxy, element);
}
for (Object element : newPropertyElementsToAdd) {
propertyAccessor.addToValue(proxy, element);
}
// if the property is a list we may restore the element order and be
// careful not to miss one...
if (actualNewProperty instanceof List) {
Collection<Object> currentProperty = (Collection<Object>) oldProperty;
List<Object> snapshot = new ArrayList<Object>(currentProperty);
if (currentProperty instanceof List) {
// Just check that only order differs
Set<Object> temp = new HashSet<Object>(currentProperty);
temp.removeAll((List<?>) actualNewProperty);
currentProperty.clear();
currentProperty.addAll((List<?>) actualNewProperty);
currentProperty.addAll(temp);
oldProperty = snapshot;
}
}
}
} catch (RuntimeException ex) {
rollbackProperty(proxy, propertyDescriptor, oldProperty);
throw ex;
} catch (InvocationTargetException ex) {
rollbackProperty(proxy, propertyDescriptor, oldProperty);
if (ex.getCause() instanceof RuntimeException) {
throw (RuntimeException) ex.getCause();
}
throw new ComponentException(ex.getCause());
} catch (IllegalAccessException ex) {
throw new ComponentException(ex);
} catch (NoSuchMethodException ex) {
throw new ComponentException(ex);
}
} else {
storeProperty(propertyName, actualNewProperty);
}
firePropertyChange(propertyName, oldProperty, actualNewProperty);