package er.directtoweb.components.relationships; import com.webobjects.appserver.WOContext; import com.webobjects.directtoweb.D2WDisplayBoolean; import com.webobjects.foundation.NSArray; /** * Allows for a flag if an object has a given related object. Given a "User" with a "groups" * relationship to a "Group" entity, you can have a list page for your users and tabular display * if a user is in a group or not. You need some rules like: * <pre><code> * 100 : (task = 'list') and (entity.name = "User") => displayPropertyKeys = (name, "groups.@Admin", "groups.@Accounting") * 100 : (task = 'list') and (entity.name = "User") and (propertyKey like 'groups.*') => componentName = "ERD2WDisplayRelationshipFlag" * 100 : (entity.name = 'Group') => keyWhenRelationship = "name" * 100 : (propertyKey = 'groups.@Admin') => displayNameForProperty = "Admin" * 100 : (propertyKey = 'groups.@Accounting') => displayNameForProperty = "Accounting" * </code></pre> * However, this might be too much work, as you need to change the rules anytime you add or remove * from the Group entity. To automatically display possible values from the Group entity, use * the ERDDelayedRelationshipFlagAssignment: * <pre><code> * 100 : (task = 'list') and (entity.name = "User") => displayPropertyKeys = (name, "@groups") [er.directtoweb.ERDDelayedRelationshipFlagAssignment] * 100 : (task = 'list') and (entity.name = "User") and (propertyKey like 'groups.*') => componentName = "ERD2WDisplayRelationshipFlag" * 100 : (entity.name = 'Group') => keyWhenRelationship = "name" * 100 : (propertyKey like 'groups.@*') => displayNameForProperty = '<computed>' [er.directtoweb.ERDDelayedRelationshipFlagAssignment] * 100 : (propertyKey like 'groups.@*') => restrictedChoiceKey = "session.possibleGroups" * </code></pre> * The "@" in the displayPropertyKeys rule is the flag that tells the assignment which relationship to * expand. Together with a method that returns the candidates for the Group entity in the Session class, you now have an * automatic display of boolean flags: * <pre><code> * Name | Admin | Accounting | Marketing * ------------------------------------------ * Fred | [x] | [ ] | [ ] * Carl | [ ] | [x] | [x] * Suzi | [x] | [ ] | [ ] * </code></pre> * Note that the ERDDelayedRelationshipFlagAssignment gets called up pretty often, so you might need to make your * candidate method in the session cache the keys. * * @author ak * @d2wKey keyWhenRelationship */ public class ERD2WDisplayRelationshipFlag extends D2WDisplayBoolean { /** * 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; public ERD2WDisplayRelationshipFlag(WOContext context) { super(context); } @Override public Object objectPropertyValue() { String propertyKey = d2wContext().propertyKey(); int index = propertyKey.indexOf(".@"); if(index > -1) { String keyPath = propertyKey.substring(0, index); String value = propertyKey.substring(index+2); d2wContext().setPropertyKey(propertyKey); Object o = object().valueForKeyPath(keyPath + "." + d2wContext().valueForKey("keyWhenRelationship")); d2wContext().setPropertyKey(propertyKey); if (o instanceof NSArray) { NSArray array = (NSArray) o; return array.containsObject(value) ? Boolean.TRUE : Boolean.FALSE; } return (o != null && o.equals(value) ? Boolean.TRUE : Boolean.FALSE); } return Boolean.FALSE; } }