package er.extensions.partials; import java.util.Collection; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableDictionary; import com.webobjects.foundation.NSValidation; import com.webobjects.foundation._NSUtilities; import er.extensions.eof.ERXEntityClassDescription; import er.extensions.eof.ERXGenericRecord; /** * For overview information on partials, read the {@code package.html} in * {@code er.extensions.partials}. * <p> * {@code ERXPartialGenericRecord} is the base class of any entity that allows * itself to be extended with partials. * * @author mschrag */ public class ERXPartialGenericRecord extends ERXGenericRecord { /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; private NSDictionary<Class, ERXPartial> _partials; @SuppressWarnings("unchecked") public NSDictionary<Class, ERXPartial> _partialsDictionary() { if (_partials == null) { ERXEntityClassDescription cd = (ERXEntityClassDescription) classDescription(); NSArray<Class<ERXPartial>> partialEntityClasses = cd.partialClasses(); if (partialEntityClasses == null || partialEntityClasses.count() == 0) { _partials = NSMutableDictionary.EmptyDictionary; } else { NSMutableDictionary<Class, ERXPartial> partials = new NSMutableDictionary<>(); for (Class<ERXPartial> partialEntityClass : partialEntityClasses) { try { ERXPartial partial = partialEntityClass.newInstance(); partial.setPrimaryEO(this); partials.setObjectForKey(partial, partialEntityClass); } catch (Exception e) { throw new RuntimeException("Failed to create the partial '" + partialEntityClass.getSimpleName() + "' for the EO '" + this + "'.", e); } } _partials = partials; } } return _partials; } public Collection<ERXPartial> _partials() { return _partialsDictionary().values(); } /** * Returns the ERXPartial partial implementation for the given partial type. * * @param <U> * the partial type * @param partialClass * the partial type * @return an instance of the given partial associated with this EO */ @SuppressWarnings("unchecked") public <U extends ERXPartial> U partialForClass(Class<U> partialClass) { U partial = (U) _partialsDictionary().objectForKey(partialClass); if (partial == null) { throw new IllegalArgumentException("There is no partial '" + partialClass.getSimpleName() + "' for the EO '" + this + "'."); } return partial; } @SuppressWarnings("unchecked") @Override public Object valueForKey(String key) { if (key != null && key.charAt(0) == '@') { return partialForClass(_NSUtilities.classWithName(key.substring(1))); } return super.valueForKey(key); } @Override public void delete() { for (ERXPartial partial : _partials()) { partial.delete(); } super.delete(); } @Override public void mightDelete() { super.mightDelete(); for (ERXPartial partial : _partials()) { partial.mightDelete(); } } @Override public void willDelete() throws NSValidation.ValidationException { super.willDelete(); for (ERXPartial partial : _partials()) { partial.willDelete(); } } @Override public void willInsert() { super.willInsert(); for (ERXPartial partial : _partials()) { partial.willInsert(); } } @Override public void willUpdate() { super.willUpdate(); for (ERXPartial partial : _partials()) { partial.willUpdate(); } } @Override public void didDelete(EOEditingContext ec) { super.didDelete(ec); for (ERXPartial partial : _partials()) { partial.didDelete(ec); } } @Override public void didUpdate() { super.didUpdate(); for (ERXPartial partial : _partials()) { partial.didUpdate(); } } @Override public void didInsert() { super.didInsert(); for (ERXPartial partial : _partials()) { partial.didInsert(); } } @Override public void willRevert() { super.willRevert(); for (ERXPartial partial : _partials()) { partial.willRevert(); } } @Override public void didRevert(EOEditingContext ec) { super.didRevert(ec); for (ERXPartial partial : _partials()) { partial.didRevert(ec); } } @Override public void awakeFromInsertion(EOEditingContext editingContext) { super.awakeFromInsertion(editingContext); for (ERXPartial partial : _partials()) { partial.init(editingContext); } } @Override protected void init(EOEditingContext editingContext) { super.init(editingContext); // Call init() on all partial entities for (ERXPartial partial : _partials()) { partial.init(editingContext); } } @Override public void awakeFromFetch(EOEditingContext editingContext) { super.awakeFromFetch(editingContext); for (ERXPartial partial : _partials()) { partial.awakeFromFetch(editingContext); } } @Override protected Object _validateValueForKey(Object value, String key) throws ValidationException { Object result = value; for (ERXPartial partial : _partials()) { result = partial.validateValueForKey(result, key); } return result; } @Override public Object validateTakeValueForKeyPath(Object value, String keyPath) throws ValidationException { Object result = super.validateTakeValueForKeyPath(value, keyPath); for (ERXPartial partial : _partials()) { if (partial.isPartialKeypath(keyPath)) { result = partial.validateTakeValueForKeyPath(result, keyPath); } } return result; } @Override public void validateForSave() throws NSValidation.ValidationException { super.validateForSave(); for (ERXPartial partial : _partials()) { partial.validateForSave(); } } @Override public void validateForInsert() throws NSValidation.ValidationException { super.validateForInsert(); for (ERXPartial partial : _partials()) { partial.validateForInsert(); } } @Override public void validateForUpdate() throws NSValidation.ValidationException { super.validateForUpdate(); for (ERXPartial partial : _partials()) { partial.validateForUpdate(); } } }