/*
* Copyright (C) NetStruxr, Inc. All rights reserved.
*
* This software is published under the terms of the NetStruxr
* Public Software License version 0.5, a copy of which has been
* included with this distribution in the LICENSE.NPL file. */
package er.directtoweb.components;
import java.util.Enumeration;
import org.apache.log4j.Logger;
import com.webobjects.appserver.WOAssociation;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WORequest;
import com.webobjects.appserver.WOResponse;
import com.webobjects.appserver.WOSession;
import com.webobjects.directtoweb.D2WComponent;
import com.webobjects.directtoweb.D2WContext;
import com.webobjects.directtoweb.D2WModel;
import com.webobjects.directtoweb.D2WSwitchComponent;
import com.webobjects.directtoweb.ERD2WContext;
import com.webobjects.directtoweb.ERD2WUtilities;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOModelGroup;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSLog;
import com.webobjects.foundation.NSMutableDictionary;
// This works around the following bug: if you switch the pageConfiguration and refresh the page,
// the context is not regenerated. This is only used for nested configurations.
// FIXME: This should be re-written as a Dynamic element.
// the right way to go is probably to use EOSwitchComponent
/**
* Rewrite of D2WSwitchComponent to not cache the D2WContext. Useful for nesting
* configurations.
*/
public class ERD2WSwitchComponent extends D2WSwitchComponent {
/**
* 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;
/** logging support */
public static final Logger log = Logger.getLogger(ERD2WSwitchComponent.class);
protected transient NSMutableDictionary<String, Object> extraBindings = new NSMutableDictionary<>(16);
public ERD2WSwitchComponent(WOContext context) {
super(context);
}
/**
* Calling super is a bad thing with 5.2. Will perform binding checks that
* shouldn't be done.
*/
@Override
public void awake() {
}
//FIXME resetting the caches breaks the context in the embedded component
public void resetCaches() {
//log.debug("Resetting caches");
//takeValueForKey(null,"_task"); // this will break in 5.0 :-)
//takeValueForKey(null,"_entityName");
// Finalizing a context is a protected method, hence the utility.
//ERD2WUtilities.finalizeContext((D2WContext)valueForKey("subContext"));
//takeValueForKey(null,"_context");
//HACK HACK HACK ak: When you have several embedded list components in
// a tab page
// D2W gets very confused about the keys. It will assume that the
// objects on the second tab somehow belong to the first
// resetting the cache when setting a new page configuration prevents
// this
D2WContext subContext = (D2WContext) valueForKey("subContext");
ERD2WUtilities.resetContextCache(subContext);
subContext.setDynamicPage((String) valueForBinding("_dynamicPage"));
subContext.takeValueForKey(D2WModel.One, D2WModel.FrameKey);
subContext.takeValueForKey(session(), D2WModel.SessionKey);
}
private String _pageConfiguration;
public void maybeResetCaches() {
String currentPageConfiguration = (String) valueForBinding("_dynamicPage");
if (_pageConfiguration != null && currentPageConfiguration != null && !_pageConfiguration.equals(currentPageConfiguration)) {
resetCaches();
}
if (currentPageConfiguration != null) _pageConfiguration = currentPageConfiguration;
}
@Override
public void appendToResponse(WOResponse r, WOContext c) {
maybeResetCaches();
super.appendToResponse(r, c);
}
@Override
public void takeValuesFromRequest(WORequest r, WOContext c) {
maybeResetCaches();
super.takeValuesFromRequest(r, c);
}
private D2WContext _context;
@Override
public D2WContext subContext() {
if (_context == null) {
String s = hasBinding("_dynamicPage") ? (String) valueForBinding("_dynamicPage") : null;
if (s != null) {
_context = makeSubContextForDynamicPageNamed(s, session());
} else {
_context = makeSubContextForTaskAndEntity(task(), EOModelGroup.defaultGroup().entityNamed(entityName()), session());
}
String s1 = lookFromSettings();
if (s1 != null) {
_context.takeValueForInferrableKey(lookFromSettings(), D2WModel.LookKey);
}
_context.takeValueForKey(_context.task() + "CurrentObject", D2WComponent
.keyForGenerationReplacementForVariableNamed("currentObject"));
}
NSDictionary nsdictionary = settings();
if (nsdictionary != null) {
String s2;
for (Enumeration enumeration = nsdictionary.keyEnumerator(); enumeration.hasMoreElements(); _context.takeValueForInferrableKey(
nsdictionary.valueForKey(s2), s2)) {
s2 = (String) enumeration.nextElement();
}
}
if (log.isDebugEnabled()) log.debug(hashCode() + ": context: " + _context);
return _context;
}
public static D2WContext makeSubContextForTaskAndEntity(String s, EOEntity eoentity, WOSession wosession) {
D2WContext d2wcontext = ERD2WContext.newContext(wosession);
d2wcontext.setTask(s);
d2wcontext.setEntity(eoentity);
d2wcontext.takeValueForKey(D2WModel.One, D2WModel.FrameKey);
return d2wcontext;
}
public static D2WContext makeSubContextForDynamicPageNamed(String s, WOSession wosession) {
D2WContext d2wcontext = ERD2WContext.newContext(wosession);
d2wcontext.setDynamicPage(s);
// NOTE AK: for whatever reason, when you set a page config
d2wcontext.setEntity(d2wcontext.entity());
d2wcontext.setTask(d2wcontext.task());
d2wcontext.takeValueForKey(D2WModel.One, D2WModel.FrameKey);
return d2wcontext;
}
@Override
public void validationFailedWithException(Throwable e, Object value, String keyPath) {
parent().validationFailedWithException(e, value, keyPath);
}
@Override
public NSDictionary extraBindings() {
if(extraBindings == null) {
extraBindings = new NSMutableDictionary<>(16);
}
extraBindings.removeAllObjects();
Enumeration e = possibleBindings.elements();
do {
if (!e.hasMoreElements())
break;
String key = (String) e.nextElement();
if (hasBinding(key)) {
Object value = valueForBinding(key);
if (value != null)
extraBindings.setObjectForKey(value, key);
else
extraBindings.setObjectForKey(NSKeyValueCoding.NullValue, key);
}
} while (true);
return extraBindings;
}
@Override
public void setExtraBindings(Object newValue) {
extraBindings = (NSMutableDictionary) newValue;
Enumeration e = possibleBindings.elements();
do {
if (!e.hasMoreElements())
break;
String key = (String) e.nextElement();
if (hasBinding(key) && associationWithName(key).isValueSettableInComponent(this))
setValueForBinding(extraBindings.objectForKey(key), key);
} while (true);
}
private WOAssociation associationWithName(String name) {
WOAssociation result = _keyAssociations.objectForKey(name);
if (result == null) {
NSLog.err.appendln(new StringBuilder().append("DirectToWeb - association with name ").append(name)
.append(" not found on ").append(this).toString());
throw new IllegalArgumentException(new StringBuilder().append("DirectToWeb - association with name ")
.append(name).append(" not found on ").append(this).toString());
} else {
return result;
}
}
}