/** Represents the <code>null</code> value in the EllaScript language. */ public class NullImpl extends AbstractObj implements NativeObj, Null { public static int OBJECT_ID = ProtoRegistry.generateObjectID(); /** A hint to the type this null value was intended to have. */ public final Class<?> typeHint; /** Creates a new null value. */ public NullImpl() { this(null); } /** * Creates a new null value with the given class indiciating it's intended type. * * @param typeHint the type hint. */ public NullImpl(Class<?> typeHint) { this.typeHint = typeHint; } /** * NOTE: Undefined variables in scripts will have the null value (Null.instance) assigned. NOTE: * With specifying a special constructor for the Null object we ensure nothing is created NOTE: * out of null. TODO: Maybe we should throw an expception instead of just returning null... */ protected static final NativeCall NATIVE_CONSTRUCTOR = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { return engine.getObjNull(); } }; public Class<?> getTypeHint() { return typeHint; } public int getObjectID() { return OBJECT_ID; } /** * Registers this EllaScript object within the given execution context. * * @param ctx the execution context to register this object in. */ public static void registerInContext(Context ctx) { NullProto.registerInContext(ctx); ctx.registerProto(OBJECT_ID, NullProto.OBJECT_ID); if (!ctx.hasObject(OBJECT_ID)) { ctx.registerObject(new NullImpl()); } } public Call getNativeConstructor() { return NATIVE_CONSTRUCTOR; } @Override public Object toJavaObject() { return null; } public String toString() { return "Null"; } protected static class NullProto extends AbstractObj { public static final int OBJECT_ID = ProtoRegistry.generateObjectID(); protected static final NativeCall nativeIdentical = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { NullImpl thiz = ensureType(NullImpl.class, context); return thiz.getClass() == args[0].getClass() ? engine.getObjTrue() : engine.getObjFalse(); } }; protected static final NativeCall nativeNotIdentical = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { NullImpl thiz = ensureType(NullImpl.class, context); return thiz.getClass() != args[0].getClass() ? engine.getObjTrue() : engine.getObjFalse(); } }; protected static final NativeCall nativeType = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { JClass typeHint = ensureType(JClass.class, args[0]); return new NullImpl(typeHint.clazz); } }; protected static final NativeCall nativeAnd = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { return engine.getObjFalse(); } }; protected static final NativeCall nativeOr = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { Clos closure = ensureType(Clos.class, args[0]); engine.trigger(closure); return null; } }; protected static final NativeCall nativeNot = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { return engine.getObjTrue(); } }; private NullProto() { slots.put(Str.SYM__id, nativeIdentical); slots.put(Str.SYM__eq, nativeIdentical); slots.put(Str.SYM__ni, nativeNotIdentical); slots.put(Str.SYM__ne, nativeNotIdentical); slots.put(Str.SYM__logic_and, nativeAnd); slots.put(Str.SYM__logic_or, nativeOr); slots.put(Str.SYM__logic_not, nativeNot); slots.put(Str.SYM_not, nativeNot); slots.put(Str.SYM_type, nativeType); } @Override public int getObjectID() { return OBJECT_ID; } public static void registerInContext(Context ctx) { Base.registerInContext(ctx); ctx.registerProto(OBJECT_ID, Base.OBJECT_ID); ctx.registerObject(new NullProto()); } } }
protected static class NullProto extends AbstractObj { public static final int OBJECT_ID = ProtoRegistry.generateObjectID(); protected static final NativeCall nativeIdentical = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { NullImpl thiz = ensureType(NullImpl.class, context); return thiz.getClass() == args[0].getClass() ? engine.getObjTrue() : engine.getObjFalse(); } }; protected static final NativeCall nativeNotIdentical = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { NullImpl thiz = ensureType(NullImpl.class, context); return thiz.getClass() != args[0].getClass() ? engine.getObjTrue() : engine.getObjFalse(); } }; protected static final NativeCall nativeType = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { JClass typeHint = ensureType(JClass.class, args[0]); return new NullImpl(typeHint.clazz); } }; protected static final NativeCall nativeAnd = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { return engine.getObjFalse(); } }; protected static final NativeCall nativeOr = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { Clos closure = ensureType(Clos.class, args[0]); engine.trigger(closure); return null; } }; protected static final NativeCall nativeNot = new NativeCall() { public Obj call(Engine engine, Obj context, Obj... args) throws ClosureTerminatedException { return engine.getObjTrue(); } }; private NullProto() { slots.put(Str.SYM__id, nativeIdentical); slots.put(Str.SYM__eq, nativeIdentical); slots.put(Str.SYM__ni, nativeNotIdentical); slots.put(Str.SYM__ne, nativeNotIdentical); slots.put(Str.SYM__logic_and, nativeAnd); slots.put(Str.SYM__logic_or, nativeOr); slots.put(Str.SYM__logic_not, nativeNot); slots.put(Str.SYM_not, nativeNot); slots.put(Str.SYM_type, nativeType); } @Override public int getObjectID() { return OBJECT_ID; } public static void registerInContext(Context ctx) { Base.registerInContext(ctx); ctx.registerProto(OBJECT_ID, Base.OBJECT_ID); ctx.registerObject(new NullProto()); } }