I have one bothering situation.
I have some parameters used in multiple nodes. By manually editing them in **NodeFactory.xml, it gets inconsistence soon.
So, I wonder
if there are some examples to unify the node name and descriptions in **NodeFactory.xml for the same variables?
I have some ideas in mind, but not sure if it works.
Put the common parameters in one .java file. Use it in *NodeFactory.xml. (after searching online, it seems not possible)
Create another .xml file, or .properties files to store parameters, and refer them in *NodeFactory.xml.
In this way, it creates a different format like the current .*NodeFactory.xml. Therefore, I worry that it can not be read right.
It’s not entirely trivial (OK, actually building up the node description text is a bit of a pain this way), but you can generate the node description from Java rather than the NodeFactory.xml file. There are several things you need to do:
You need to create a subclass of NodeDescription - in your case it sounds like you could create an abstract implementation with some method hooks to add in the relevant detail differences for different nodes
You also need to override the default implementation of #createNodeDescription() in your NodeFactory class implementation to return an instance of your NodeDescription class.
If you need to load additional NodeFactory settings, or instantiate some fields in the NodeFactory implementation prior to the framework’s call to #createNodeDescription(), you will need to use the ‘lazy’ constructor for the node factory, manually perform an initialisation and then call #init(), either at the end of your constructor or at the end of your #loadAdditionalFactorySettings() method
If you use this approach you will not automatically get the handy footer on the node description showing the plugin contributing the node:
* Method to add the vendor bundle information to the node description. For
* nodes with an XML Node description, this is performed dynamically,
* however when the node description is supplied dynamically this needs to
* be added manually. This version does not require an instance of the
* {@link NodeFactory} class
*
* @param node
* The KnimeNode element
* @param nodeFactoryClazz
* The {@link NodeFactory} instance
* @throws DOMException
*/
public static void addBundleInformation(KnimeNode node,
Class<? extends NodeFactory<?>> nodeFactoryClazz)
throws DOMException {
Element bundleElement = ((Element) node.getDomNode()).getOwnerDocument()
.createElement("osgi-info");
Bundle bundle = OSGIHelper.getBundle(nodeFactoryClazz);
if (bundle != null) {
Optional<IInstallableUnit> feature = OSGIHelper.getFeature(bundle);
bundleElement.setAttribute("bundle-symbolic-name", feature
.map(f -> f.getId()).orElse(bundle.getSymbolicName()));
bundleElement.setAttribute("bundle-name", feature
.map(f -> f.getProperty(IInstallableUnit.PROP_NAME, null))
.orElse(bundle.getHeaders().get("Bundle-Name")));
bundleElement.setAttribute("bundle-vendor", feature.map(
f -> f.getProperty(IInstallableUnit.PROP_PROVIDER, null))
.orElse(bundle.getHeaders().get("Bundle-Vendor")));
} else {
bundleElement.setAttribute("bundle-symbolic-name", "<Unknown>");
bundleElement.setAttribute("bundle-name", "<Unknown>");
bundleElement.setAttribute("bundle-vendor", "<Unknown>");
}
bundleElement.setAttribute("factory-package",
nodeFactoryClazz.getPackage().getName());
((Element) node.getDomNode()).appendChild(bundleElement);
}
There is also another subtle advantage of this approach. If you use static constants with package visibility in your Node Settings Pane class for the actual option names shown in the node settings panel, then you can use those constants in the NodeDescription too - guaranteeing that whatever is displayed in the dialog matches exactly what is displayed in the node description!