org.mvel2.ast.Proto Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of virtdata-lib-realer Show documentation
Show all versions of virtdata-lib-realer Show documentation
With inspiration from other libraries
package org.mvel2.ast;
import org.mvel2.CompileException;
import org.mvel2.ParserContext;
import org.mvel2.UnresolveablePropertyException;
import org.mvel2.compiler.ExecutableStatement;
import org.mvel2.integration.VariableResolver;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.integration.impl.MapVariableResolverFactory;
import org.mvel2.integration.impl.SimpleValueResolver;
import org.mvel2.util.CallableProxy;
import org.mvel2.util.SimpleIndexHashMapWrapper;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import static org.mvel2.DataConversion.canConvert;
import static org.mvel2.DataConversion.convert;
public class Proto extends ASTNode {
private String name;
private Map receivers;
private int cursorStart;
private int cursorEnd;
public Proto(String name, ParserContext pCtx) {
super(pCtx);
this.name = name;
this.receivers = new SimpleIndexHashMapWrapper();
}
public Receiver declareReceiver(String name, Function function) {
Receiver r = new Receiver(null, ReceiverType.FUNCTION, function);
receivers.put(name, r);
return r;
}
public Receiver declareReceiver(String name, Class type, ExecutableStatement initCode) {
Receiver r = new Receiver(null, ReceiverType.PROPERTY, initCode);
receivers.put(name, r);
return r;
}
public Receiver declareReceiver(String name, ReceiverType type, ExecutableStatement initCode) {
Receiver r = new Receiver(null, type, initCode);
receivers.put(name, r);
return r;
}
public ProtoInstance newInstance(Object ctx, Object thisCtx, VariableResolverFactory factory) {
return new ProtoInstance(this, ctx, thisCtx, factory);
}
@Override
public Object getReducedValue(Object ctx, Object thisValue, VariableResolverFactory factory) {
factory.createVariable(name, this);
return this;
}
@Override
public Object getReducedValueAccelerated(Object ctx, Object thisValue, VariableResolverFactory factory) {
factory.createVariable(name, this);
return this;
}
public class Receiver implements CallableProxy {
private ReceiverType type;
private Object receiver;
private ExecutableStatement initValue;
private ProtoInstance instance;
public Receiver(ProtoInstance protoInstance, ReceiverType type, Object receiver) {
this.instance = protoInstance;
this.type = type;
this.receiver = receiver;
}
public Receiver(ProtoInstance protoInstance, ReceiverType type, ExecutableStatement stmt) {
this.instance = protoInstance;
this.type = type;
this.initValue = stmt;
}
public Object call(Object ctx, Object thisCtx, VariableResolverFactory factory, Object[] parms) {
switch (type) {
case FUNCTION:
return ((Function) receiver).call(ctx, thisCtx, new InvokationContextFactory(factory, instance.instanceStates), parms);
case PROPERTY:
return receiver;
case DEFERRED:
throw new CompileException("unresolved prototype receiver", expr, start);
}
return null;
}
public Receiver init(ProtoInstance instance, Object ctx, Object thisCtx, VariableResolverFactory factory) {
return new Receiver(instance, type,
type == ReceiverType.PROPERTY && initValue != null ? initValue.getValue(ctx, thisCtx, factory) :
receiver);
}
public void setType(ReceiverType type) {
this.type = type;
}
public void setInitValue(ExecutableStatement initValue) {
this.initValue = initValue;
}
}
public enum ReceiverType {
DEFERRED, FUNCTION, PROPERTY
}
public class ProtoInstance implements Map {
private Proto protoType;
private VariableResolverFactory instanceStates;
private SimpleIndexHashMapWrapper receivers;
public ProtoInstance(Proto protoType, Object ctx, Object thisCtx, VariableResolverFactory factory) {
this.protoType = protoType;
receivers = new SimpleIndexHashMapWrapper();
for (Map.Entry entry : protoType.receivers.entrySet()) {
receivers.put(entry.getKey(), entry.getValue().init(this, ctx, thisCtx, factory));
}
instanceStates = new ProtoContextFactory(receivers);
}
public Proto getProtoType() {
return protoType;
}
public int size() {
return receivers.size();
}
public boolean isEmpty() {
return receivers.isEmpty();
}
public boolean containsKey(Object key) {
return receivers.containsKey(key);
}
public boolean containsValue(Object value) {
return receivers.containsValue(value);
}
public Receiver get(Object key) {
return receivers.get(key);
}
public Receiver put(String key, Receiver value) {
return receivers.put(key, value);
}
public Receiver remove(Object key) {
return receivers.remove(key);
}
public void putAll(Map m) {
}
public void clear() {
}
public Set keySet() {
return receivers.keySet();
}
public Collection values() {
return receivers.values();
}
public Set> entrySet() {
return receivers.entrySet();
}
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return "proto " + name;
}
public class ProtoContextFactory extends MapVariableResolverFactory {
private final SimpleIndexHashMapWrapper variableResolvers;
public ProtoContextFactory(SimpleIndexHashMapWrapper variables) {
super(variables);
variableResolvers = new SimpleIndexHashMapWrapper(variables, true);
}
@Override
public VariableResolver createVariable(String name, Object value) {
VariableResolver vr;
try {
(vr = getVariableResolver(name)).setValue(value);
return vr;
}
catch (UnresolveablePropertyException e) {
addResolver(name, vr = new ProtoResolver(variables, name)).setValue(value);
return vr;
}
}
@Override
public VariableResolver createVariable(String name, Object value, Class> type) {
VariableResolver vr;
try {
vr = getVariableResolver(name);
}
catch (UnresolveablePropertyException e) {
vr = null;
}
if (vr != null && vr.getType() != null) {
throw new CompileException("variable already defined within scope: " + vr.getType() + " " + name, expr, start);
}
else {
addResolver(name, vr = new ProtoResolver(variables, name, type)).setValue(value);
return vr;
}
}
@Override
public void setIndexedVariableNames(String[] indexedVariableNames) {
//
}
@Override
public String[] getIndexedVariableNames() {
//
return null;
}
@Override
public VariableResolver createIndexedVariable(int index, String name, Object value, Class> type) {
VariableResolver vr = this.variableResolvers != null ? this.variableResolvers.getByIndex(index) : null;
if (vr != null && vr.getType() != null) {
throw new CompileException("variable already defined within scope: " + vr.getType() + " " + name, expr, start);
}
else {
return createIndexedVariable(variableIndexOf(name), name, value);
}
}
@Override
public VariableResolver createIndexedVariable(int index, String name, Object value) {
VariableResolver vr = variableResolvers.getByIndex(index);
if (vr == null) {
vr = new SimpleValueResolver(value);
variableResolvers.putAtIndex(index, vr);
}
else {
vr.setValue(value);
}
return indexedVariableResolvers[index];
}
@Override
public VariableResolver getIndexedVariableResolver(int index) {
return variableResolvers.getByIndex(index);
}
@Override
public VariableResolver setIndexedVariableResolver(int index, VariableResolver resolver) {
variableResolvers.putAtIndex(index, resolver);
return resolver;
}
@Override
public int variableIndexOf(String name) {
return variableResolvers.indexOf(name);
}
public VariableResolver getVariableResolver(String name) {
VariableResolver vr = variableResolvers.get(name);
if (vr != null) {
return vr;
}
else if (variables.containsKey(name)) {
variableResolvers.put(name, vr = new ProtoResolver(variables, name));
return vr;
}
else if (nextFactory != null) {
return nextFactory.getVariableResolver(name);
}
throw new UnresolveablePropertyException("unable to resolve variable '" + name + "'");
}
}
public class ProtoResolver implements VariableResolver {
private String name;
private Class> knownType;
private Map variableMap;
public ProtoResolver(Map variableMap, String name) {
this.variableMap = variableMap;
this.name = name;
}
public ProtoResolver(Map variableMap, String name, Class knownType) {
this.name = name;
this.knownType = knownType;
this.variableMap = variableMap;
}
public void setName(String name) {
this.name = name;
}
public void setStaticType(Class knownType) {
this.knownType = knownType;
}
public String getName() {
return name;
}
public Class getType() {
return knownType;
}
public void setValue(Object value) {
if (knownType != null && value != null && value.getClass() != knownType) {
if (!canConvert(knownType, value.getClass())) {
throw new CompileException("cannot assign " + value.getClass().getName() + " to type: "
+ knownType.getName(), expr, start);
}
try {
value = convert(value, knownType);
}
catch (Exception e) {
throw new CompileException("cannot convert value of " + value.getClass().getName()
+ " to: " + knownType.getName(), expr, start);
}
}
((Receiver) variableMap.get(name)).receiver = value;
}
public Object getValue() {
return ((Receiver) variableMap.get(name)).receiver;
}
public int getFlags() {
return 0;
}
}
public void setCursorPosition(int start, int end) {
this.cursorStart = start;
this.cursorEnd = end;
}
public int getCursorStart() {
return cursorStart;
}
public int getCursorEnd() {
return cursorEnd;
}
}