Runtime Xtemplate or drop-in templates?

I have a client that is currently displaying a list of search results. The search results can come from multiple sources, all which have their own data structure. Currently I have a map that diagnoses which template to use and returns the correct template to render in my list (i.e. using new SimpleSafeHtmlCell<Hit> and returning the correct XTemplate safehtml). Is there a way to drop in templates at runtime? I figured I could use javascript to diagnose which template to return.

If not, is there a better approach to avoid compiling things into SafeHTML and be able to have runtime templating?

The gxt-legacy.jar has the 2.x style XTemplates, which allow them to be compiled from runtime strings, and to give up the ability to have them compiled. Of course, you'll need to use data models that can be introspected at runtime, so normal beans won't work - the compiler renames those fields, so the runtime xtemplates can't turn {user.name} into {f.c}.

XTemplates only can operate on JSOs, so yes, that can be convenient to have - if your data model can be made into JSOs, that would work well. That said, there are mechanical processes that can turn bean-like objects or other Java types into JSO.

JsoReader (NOT JsonReader, note the missing 'n') is the reverse of this process - we don't a 'JsoWriter', it not being usually too terrible useful. These types all use AutoBeans, which make the string names of each property (get/set method) available at compile time.

The 3.x legacy jar also has the ModelData interface and BaseModelData classes, which can go over the wire using RPC. There is no provided mechanism to turn them into a JSO, though one exists in 2.x and could be easily ported. Check out com.extjs.gxt.ui.client.util.Util.getJsObject(ModelData) - I'm not certain why it was omitted from 3.x's legacy jar, but will look into it for an upcoming release. The com.sencha.gxt.legacy.client.core.js.JsUtil class does have a toJavaScriptObject(Map<String, V>) method, and that needs the map from within a BaseModelData, but has no support for collections.

The important thing in all of these is that the names of each property has to be available at runtime. Without that, you can't get an create a JSO with the properties that the XTemplate expects to find.

So just to clarify, as I am about to start implementing these changes...

Right now I have the JsonReader class handling things coming back from a HTTPProxy (both being wrapped in a paging loader). The POJO objects these get handled with are all Autobeans.

The next step would be to modify my POJO objects to be JSO Overlays that can deserialized from the incoming JSON (still figuring this part out) and then provide the templates at run-time?

Does that sound correct? Maybe extending JsoReader to parse Json into JSO Autobean? I guess I'm confused where Autobeans come into play and if I still need them, as I'm just handling JSON strings and need a JSO Overlay?

Provided you are already using autobeans elsewhere in your app (and I'm assuming you are, since you are also using a loader, proxy, reader - these tools aren't required just to read in a model and display it with a template), turning an JSON-based autobean into a JSO shouldn't be too bad.

When your app is compiled, it already *is* a JSO, and the autobean wrapping is just enough reflection details to map to the json stream you are sending over the wire. When you are in Dev Mode, however, you'll probably need to do some additional wrapping, since in dev mode a json-based autobean is backed by the json.jar tools. This would be my first try to handle this - I'd write a sort of JsoWriter class, like what we have already in JsoReader (except backwards). Using the AutoBeanUtils.getAutoBean class to get the AutoBean instance, then grab the underlying Splittable object. It'll be a JsoSplittable when isScript() is true, and can be treated as a real JSO, or it'll be a JsonSplittable, so you can read out the json string, then pass that through JsonUtils.safeEval(String) to get a JSO. This isn't terribly efficient, but since you are only doing it in Dev Mode, shouldn't be a major concern for real world cases.

At this point, any other approach I'd devise would be to start with taking another look at the problem and working from there - how much reflection is needed in general? Do we really need the full xtemplate language, or can we get by with some other generic way of talking about data? That said, if you've already got AutoBeans in your app, like I said above: you are already dealing with JSOs in your compiled code, so it should be cheap to read out that underlying JSO - just don't modify it as a JSO!

JsoReader will not turn JSON into a JSO. The purpose of the JsoReader is to turn a Jso (like from a JSONP request, or from some JS-based API) into a autobean.

So with this JsoWriter, I just pass my objects through it each time and then pass them to the template for rendering correct? I might take a different path as this path looks like it has a lot of overhead associated with it.

Just so I get the picture right, the code your implying looks something like the following:

Like I said, this answer assumes you already *need* that loader/reader/proxy and autobean impl - the overhead should be pretty minimal though. If you don't need those pieces, cut to the chase after getting the JSON string, and call JsonUtils.safeEval.

Two details about how you've done it:
* The abstract class AutoBeanWriter is designed to provide the getAutoBean method when you might have an object that is part autobean and part real java bean impl. This isn't needed in your case, since all data is coming from autobeans, so you can stop subclassing and calling getAutoBean. Instead, use AutoBeanUtils.getAutoBean - a much cheaper way of doing the same thing when you are sure there are no non-autobeans to worry about
* This leaves the AutoBeanCodex.encode as the only expensive call in the whole thing - this is internally turning the data into a String and then into a Splittable, to ensure that nothing gets missed. In your case, if you can assume that no data has been changed since it came over the wire, you can write a faster, cheater version of this by calling on the existing AbstractAutoBean.data member.

Finally, before obsessing over performance, as always, check if performance is acceptable. You can start with code that works, and fine tune later. Typically when dealing with large amounts of data, it isn't the processing that is costly in a browser - it is the drawing of that data. The complexity of rendering your templates will likely dwarf any data manipulation in the class you've just built - measure, then cut.