What kept me busy lately (apart from my insane work load)? Adding 'generics' support to the TOM.Java API.
I was blogging a few weeks ago about a pet project of mine -- the Java Mediator for SDL Tridion Templating. In that post I was very enthusiastic about JNI4NET bridge between Java and .NET and namely about ProxyGen -- the tool that actually generates both Java and C# proxy classes. For what it is, ProxyGen is a great tool, but it's really a Java 1.4 tool -- namely, it does not support generics. Luckily, it is open source, so anybody can modify it...
However, the problem for me was my own learning curve. ProxyGen is in fact a code generator written in C# using CodeDom, which builds a class model (from JARs and DLLs) using reflection, and finally generates C# and Java code from this model.
I won't go into the ProxyGen details here (if you want more details, I posted more details on jni4net Google group).
Anyway, with this (partial) support for generics in TOM.Java, I am able to use Java counterparts for the main generic collections from C# (and the other way around for that matter - from Java collections to C# collections). The following type mappings are available:
The methods using generics delegate their calls to the non-generic native counterparts (as originally designed by ProxyGen). What I did was basically deal with the conversion from generic to non-generic and back. The delegate methods are suffixed with the name of the Java collection they are a generic for.
Example: Package.GetEntries() returns a C# IList of KeyValuePairs of string and Item objects.
Original signature:
ProxyGen generates a Java native proxy method with signature:
If I were to use this method I would have to use the IEnumerator iterator like this (and that does not support Java for-each loops):
So the loop-above can be rewritten Java-style with for-each:
I was blogging a few weeks ago about a pet project of mine -- the Java Mediator for SDL Tridion Templating. In that post I was very enthusiastic about JNI4NET bridge between Java and .NET and namely about ProxyGen -- the tool that actually generates both Java and C# proxy classes. For what it is, ProxyGen is a great tool, but it's really a Java 1.4 tool -- namely, it does not support generics. Luckily, it is open source, so anybody can modify it...
However, the problem for me was my own learning curve. ProxyGen is in fact a code generator written in C# using CodeDom, which builds a class model (from JARs and DLLs) using reflection, and finally generates C# and Java code from this model.
I won't go into the ProxyGen details here (if you want more details, I posted more details on jni4net Google group).
Anyway, with this (partial) support for generics in TOM.Java, I am able to use Java counterparts for the main generic collections from C# (and the other way around for that matter - from Java collections to C# collections). The following type mappings are available:
Java
|
C#
|
java.util.List<E> | System.Collections.Generic.IList<T> |
java.util.Map<K, V> | System.Collections.Generic.IDictionary<K, V> |
java.util.Set<E> | System.Collections.Generic.ISet<T> |
java.util.Collection<E> | System.Collections.Generic.ICollection<T> |
java.lang.Iterable<E> | System.Collections.Generic.IEnumerable<T> |
The methods using generics delegate their calls to the non-generic native counterparts (as originally designed by ProxyGen). What I did was basically deal with the conversion from generic to non-generic and back. The delegate methods are suffixed with the name of the Java collection they are a generic for.
Example: Package.GetEntries() returns a C# IList of KeyValuePairs of string and Item objects.
Original signature:
IList<KeyValuePair<string, Item>> GetEntries()
ProxyGen generates a Java native proxy method with signature:
public native system.collections.IList GetEntries()
If I were to use this method I would have to use the IEnumerator iterator like this (and that does not support Java for-each loops):
for (IEnumerator enumerator = _package.GetEntries().GetEnumerator();
enumerator.MoveNext();) {
@SuppressWarnings("rawtypes")
KeyValuePair kvp = (KeyValuePair) enumerator.getCurrent();
system.String key =
(system.String) kvp.getKey();
Item value = (Item) kvp.getValue();
System.out.println(String.format("\tKey: %s\tValue: %s", key, value.GetAsString()));
}
Next to this, my enhancement to ProxyGen now generates a delegate that accepts generics
java.util.List<mitza.jni4net.wrapper.KeyValuePair<system.String, tridion.contentmanager.templating.Item>> GetEntriesList()
So the loop-above can be rewritten Java-style with for-each:
for (KeyValuePair<system.String, Item> kvp :
_package.GetEntriesList()) {
System.out.println(
String.format("Key: %s Value: %s", kvp.getKey(), kvp.getValue().GetAsString()));
String.format("Key: %s Value: %s", kvp.getKey(), kvp.getValue().GetAsString()));
}
Other examples:
for (ComponentPresentation cp : page.getComponentPresentationsList()) {
Component component
= cp.getComponent();
ComponentTemplate
componentTemplate = cp.getComponentTemplate();
System.out.println(String.format("CP: Component: '%s' %s + Component Template: '%s' %s",
component.getTitle(),
component.getId(), componentTemplate.getTitle(), componentTemplate.getId()));
}
for (VersionedItem item : page.GetVersionsIterable()) {
System.out.println(String.format("Version: %s User: %s Date: %s",
item.getVersion(), item.getRevisor().getTitle(),
item.getRevisionDate()));
}
Comments