package railo.runtime.type.scope;
import java.util.Iterator;
import railo.runtime.PageContext;
import railo.runtime.config.NullSupportHelper;
import railo.runtime.dump.DumpData;
import railo.runtime.dump.DumpProperties;
import railo.runtime.dump.DumpTable;
import railo.runtime.engine.ThreadLocalPageContext;
import railo.runtime.exp.PageException;
import railo.runtime.op.Duplicator;
import railo.runtime.type.Collection;
import railo.runtime.type.Struct;
public class ClosureScope extends ScopeSupport implements Variables {
private static final Object NULL = new Object();
private Argument arg;
private Local local;
private Variables var;
private boolean debug;
private Undefined und;
public ClosureScope(PageContext pc,Argument arg, Local local,Variables var ){
super("variables",SCOPE_VARIABLES,Struct.TYPE_REGULAR);
arg.setBind(true);
local.setBind(true);
var.setBind(true);
und = pc.undefinedScope();
this.arg=arg;
this.local=local;
this.var=var;
this.debug=pc.getConfig().debug();
}
@Override
public boolean isInitalized() {
return true;
}
@Override
public void initialize(PageContext pc) {
}
@Override
public void release() {
}
@Override
public void release(PageContext pc) {
}
@Override
public int getType() {
return SCOPE_VARIABLES;
}
@Override
public String getTypeAsString() {
return "variables";
}
@Override
public int size() {
return var.size();
}
@Override
public Key[] keys() {
return var.keys();
}
@Override
public Object remove(Key key) throws PageException {
if(local.containsKey(key))
return local.remove(key);
return var.remove(key);
}
@Override
public Object removeEL(Key key) {
if(local.containsKey(key))
return local.removeEL(key);
return var.removeEL(key);
}
@Override
public void clear() {
var.clear();
}
@Override
public Object get(Key key) throws PageException {
Object value = local.get(key,NullSupportHelper.NULL());
if(value!=NullSupportHelper.NULL()) return value;
value=arg.get(key,NullSupportHelper.NULL());
if(value!=NullSupportHelper.NULL()) {
if(debug) UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),arg.getTypeAsString(), key);
return value;
}
value= var.get(key);
if(debug) UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),var.getTypeAsString(), key);
return value;
}
@Override
public Object get(Key key, Object defaultValue) {
Object value = local.get(key,NullSupportHelper.NULL());
if(value!=NullSupportHelper.NULL()) return value;
value=arg.get(key,NullSupportHelper.NULL());
if(value!=NullSupportHelper.NULL()) {
if(debug) UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),arg.getTypeAsString(), key);
return value;
}
value= var.get(key,NullSupportHelper.NULL());
if(value!=NullSupportHelper.NULL()){
if(debug) UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),var.getTypeAsString(), key);
return value;
}
return defaultValue;
}
@Override
public Object set(Key key, Object value) throws PageException {
if(und.getLocalAlways() || local.containsKey(key)) return local.set(key,value);
if(arg.containsKey(key)) {
if(debug)UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),arg.getTypeAsString(), key);
return arg.set(key,value);
}
if(debug)UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),var.getTypeAsString(), key);
return var.set(key, value);
}
@Override
public Object setEL(Key key, Object value) {
if(und.getLocalAlways() || local.containsKey(key)) return local.setEL(key,value);
if(arg.containsKey(key)) {
if(debug)UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),arg.getTypeAsString(), key);
return arg.setEL(key,value);
}
if(debug)UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),var.getTypeAsString(), key);
return var.setEL(key,value);
}
@Override
public Collection duplicate(boolean deepCopy) {
return new ClosureScope(ThreadLocalPageContext.get(),(Argument)Duplicator.duplicate(arg,deepCopy), (Local)Duplicator.duplicate(local,deepCopy), (Variables)Duplicator.duplicate(var,deepCopy));
}
@Override
public boolean containsKey(Key key) {
return get(key,NULL)!=NULL;
}
@Override
public Iterator<Collection.Key> keyIterator() {
return var.keyIterator();
}
@Override
public Iterator<String> keysAsStringIterator() {
return var.keysAsStringIterator();
}
@Override
public Iterator<Entry<Key, Object>> entryIterator() {
return var.entryIterator();
}
@Override
public Iterator<Object> valueIterator() {
return var.valueIterator();
}
@Override
public void setBind(boolean bind) {}
@Override
public boolean isBind() {
return true;
}
@Override
public DumpData toDumpData(PageContext pageContext, int maxlevel,
DumpProperties properties) {
DumpTable dt= (DumpTable) super.toDumpData(pageContext, maxlevel, properties);
dt.setTitle("Closure Variable Scope");
return dt;
}
}