FScript

by murlen
[Previous] [Contents] [Next]

Java Objects

Basics

As of version 1.1 FScript has the ability to access Java objects. This is done by registering an instance of the FSReflectionExtension class. An example of this is in the examples/objects/Objects.java file:

		FSReflectionExtension fe=new FSReflectionExtension();
		BasicIO fs=new BasicIO();

		fs.registerExtension(fe);

		fs.load(new FileReader("objects.script"));
		fs.run();	

By registering a FSReflectionExtension the following functions become available within FScript:

  • create which creates a new instance of a Java object.
  • getClass which gets a reference to a Java class (allowing you to use static methods/fields)


  • For example:
    	object system,map
    	system=getClass("java.lang.System")
    	map=create("java.util.HashMap")
    

    The object type

    The object type is a special type used in FScript to contain objects. There are a few rules governing it's use.

  • An uninitialized variable may be set to any object (either external or one of FScripts own types). e.g:
    	object obj1,obj2
    	obj1=create("java.util.ArrayList")
    	obj2="This is a string"
    
  • An object can only be re-assigned with an object of the same type so, continuing from above
    	obj2="This is another string"
    
    Would be valid, but:
    	obj2=obj1
    
    would not.


  • An object variable can be cleared by assigning it the keyword null . Thus the only way to re-assign an object variable to a different type is to set it to null first e.g:
    	obj2=null
    	obj2=obj1
    
  • The object type can be used outside of the context of FSReflectionExtension . The object type is implemented using the FSObject wrapper class, so any extension/subclass is free to return a FSObject and have it handled internally within FScript as a object in much the same way as Integer,Double and String currently work.

    Using objects

    Once an object has been created it can be accessed from FScript in a similar manner to which it can be accessed in Java. Methods can be called, and fields read and set. For example (taken from objects.script in the examples directory):

    	object map,obj
    	map=create("java.util.HashMap")
    	map.put("a","Apple")
    	map.put("b","Bear")
    	map.put("c","Car")
    	map.put("d","Demolition")
    
    
    	#Create out test object
    	obj=create("TestObject")
    	obj.testMethod()
    	out.println(obj.stringField)
    	out.println(obj.intField)
    	out.println(obj.intMethod("5551212"))
    
    	#Set a field using explicit call
    	obj.setValue("Test value for object")
    	#But we could do this which is equiv to the setValue call
    	#obj.Value="Test value for object" 
    
    	#get value using the implicit getter
    	out.println(obj.Value)
    	#however we could have done this
    	#out.println(obj.getValue())
    

    As can be seen from the above code the FSReflectionExtension class also provides some support for Bean like getters and setters - i.e a line of the type:

    	myObj.Amount=12
    
    If no amount field exists, this call is converted internally to:
    	myObj.setAmount(12)
    
    A similar process takes place with assignment, with:
    	intValue=myObj.Amount
    
    potentially becoming:
    	intValue=myObj.getAmount()
    

    Exceptions

    It is possible to use a custom exception handler for calls to methods of objects created by the FSReflectionExtension . This exception handler will only be called for exceptions thrown from within the method called, not for exceptions caused by problems with parameters or method names. This can be done using the setExceptionHandler method of FSReflectionExtension .

    Limitations

    There are some limitations of FSReflectionExtension however. It is only simple to work with for parameter types etc. that are supported by FScript (Integer, Double and String), although this limitation can be worked around a little by using the object type in FScript for parameters too.

    Only one level of indirection (dots) are allowed e.g.

    	object sys
    	sys=getClass("java.lang.System")
    
    	sys.out.println("Hello")
    
    Will fail at sys.out.println("Hello") . The solution to this is to recode like:
    	object sys,out
    	sys=getClass("java.lang.System")
    	out=sys.out
    	out.println("Hello")
    
    Which is a little cumbersome, but works.

    FSReflectionExtension

    As FSReflectionExtension is an extension, rather than being directly built into FScript it would be possible to write a replacement or enhancement for the extension. FSReflectionExtension makes use of the FSParserExtension interface. This interface is simply an extension of the FSExtension interface which ensures that implementers are passed a reference to the current Parser class. It would be wise to study the source for the FSReflectionExtension before attempting to code an extension/replacement.

    Also note that the FSReflection extension makes use of code from the Apache Velocity project, which is under the Apache license. This is stated in the relevant files (murlen.util.fscript.introspection.*).


    [Previous] [Contents] [Next]

    created with DocLite