package er.extensions.components; import java.util.Enumeration; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOAssociation; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WODynamicElement; import com.webobjects.appserver.WOElement; import com.webobjects.appserver.WORequest; import com.webobjects.appserver.WOResponse; import com.webobjects.appserver._private.WODynamicGroup; import com.webobjects.appserver._private.WOHTMLBareString; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableArray; import er.extensions.components.conditionals.ERXWOTemplate; /** * Allows for multiple Component Contents. * * Currently, WOComponentContent can only access a single subtemplate. We need a * way to pass several named contents. <pre><code> ============================== Parent component: ============================== <webobject name=SomeComponent> This text will be ignored (unless you use WOComponentContent without templateName in which case the templates will get appended twice!) <webobject name=Template1> This is the first template </webobject> <webobject name=Template2> This is the second template </webobject> <webobject name=Template3> This is the third template </webobject> </webobject> =========== Parent wod: =========== SomeComponent: SomeComponent { someIvar = someValue; } Template1: ERXWOTemplate { templateName = "firstTemplate"; } Template2: ERXWOTemplate { templateName = "secondTemplate"; } Template3: ERXWOTemplate { templateName = "thirdTemplate"; } ============================== Child Component (SomeComponent) ============================== Some static html <webobject name=ComponentContent1> This is the default content if "firstTemplate" is not defined by parent </webobject> <webobject name=Repetition> <webobject name=ComponentContent3> This is the default content if "thirdTemplate" is not defined by parent </webobject> </webobject> <webobject name=ComponentContent2> This is the default content if "secondTemplate" is not defined by parent </webobject> some more static html =========== Child wod: =========== ComponentContent1: ERXWOComponentContent { templateName = "firstTemplate"; } ComponentContent2: ERXWOComponentContent { templateName = "secondTemplate"; } ComponentContent3: ERXWOComponentContent { templateName = "thirdTemplate"; } </code></pre> * * So, the way this could work is to add functionality to WOComponentContent * which allows it to iterate through its elements and locate the named * templates. It also needs to be extended so that it takes the contents of its * reference as a default if no named template is provided/found. * * <pre><code> <webobject name=IfThenElse> <webobject name=TrueBlock> This is true block </webobject> <webobject name=FalseBlock> This is false block </webobject> </webobject> IfThenElse: IfThenElseComponent { condition = someCondition; } Template1: ERXWOTemplate { templateName = "true"; } Template2: ERXWOTemplate { templateName = "false"; } </code></pre> * * @binding templateName The templateName of the ERXWOTemplate which should be rendered * in place of this element. If not set, this element will behave like * a regular WOComponentContent, but filter out all ERXWOTemplates. * * @author ak (Java port) * @author Charles Lloyd */ public class ERXWOComponentContent extends WODynamicElement { public static String WOHTMLTemplateNameAttribute = "templateName"; private WOAssociation _templateName; protected WOElement _defaultTemplate; public ERXWOComponentContent(String name, NSDictionary associations, WOElement woelement) { super(name, associations, woelement); _templateName = (WOAssociation) associations.objectForKey("templateName"); _defaultTemplate = woelement == null ? new WOHTMLBareString("") : woelement; } private WOElement template(WOComponent component) { WOElement content = component._childTemplate(); WOElement result = null; String templateName = (_templateName == null) ? null : (String) _templateName.valueInComponent(component); if (content != null && content.getClass() == WODynamicGroup.class) { WODynamicGroup group = (WODynamicGroup) content; if (templateName == null) { // MS: If you don't set a template name, then let's construct all the children of // this element that are NOT ERXWOTemplate's, so we don't double-display. This lets // you use an ERXWOComponentContent and have it just act like a "default" template // that skips all the children that are explicitly wrapped in an ERXWOTemplate. NSMutableArray<WOElement> originalChildrenElements = group.childrenElements(); if (originalChildrenElements != null && originalChildrenElements.count() > 0) { NSMutableArray<WOElement> nonTemplateChildrenElements = new NSMutableArray<>(); for (WOElement originalChild : originalChildrenElements) { if (!(originalChild instanceof ERXWOTemplate)) { nonTemplateChildrenElements.addObject(originalChild); } } result = new WODynamicGroup(null, null, nonTemplateChildrenElements); } } else { for(Enumeration e = group.childrenElements().objectEnumerator(); e.hasMoreElements() && result == null ; ) { WOElement current = (WOElement) e.nextElement(); if(current instanceof ERXWOTemplate) { ERXWOTemplate template = (ERXWOTemplate)current; String name = template.templateName(component); if(name.equals(templateName)) { result = template; } } } } } else if (content instanceof ERXWOTemplate) { ERXWOTemplate template = (ERXWOTemplate) content; String name = template.templateName(component); if(name.equals(templateName)) { result = template; } } else if (templateName == null) { result=content; } return result; } @Override public void takeValuesFromRequest(WORequest worequest, WOContext wocontext) { WOComponent component = wocontext.component(); WOElement template = template(component); if(template != null) { wocontext._setCurrentComponent(component.parent()); template.takeValuesFromRequest(worequest, wocontext); wocontext._setCurrentComponent(component); } else { _defaultTemplate.takeValuesFromRequest(worequest, wocontext); } } @Override public WOActionResults invokeAction(WORequest worequest, WOContext wocontext) { WOComponent component = wocontext.component(); WOElement template = template(component); WOActionResults result; if(template != null) { wocontext._setCurrentComponent(component.parent()); result = template.invokeAction(worequest, wocontext); wocontext._setCurrentComponent(component); } else { result = _defaultTemplate.invokeAction(worequest, wocontext); } return result; } @Override public void appendToResponse(WOResponse woresponse, WOContext wocontext) { WOComponent component = wocontext.component(); WOElement template = template(component); if(template != null) { wocontext._setCurrentComponent(component.parent()); template.appendToResponse(woresponse, wocontext); wocontext._setCurrentComponent(component); } else { _defaultTemplate.appendToResponse(woresponse, wocontext); } } @Override public String toString() { return "<" + getClass().getName() + "@" + System.identityHashCode(this) + " : " + _templateName + ">"; } }