X

Geertjan's Blog

Car Designer on the NetBeans Platform (Part 2)

Geertjan Wielenga
Product Manager
The next step of our car designer is an extension of the section "Opening the File into a Window", from the NetBeans File Type Integration Tutorial. We can now also nicely deal with a question I received yesterday from Urs Bill from Switzerland (from a team of developers working on Berne's public transportation system, which is also based on the NetBeans Platform):

"In your tutorial in the class AbcOpenSupport you create a new AbcTopComponent, set its displayName to dobj.getName() and return it. In a real world scenario would you rather pass the AbcDataObject to the just created AbcTopComponent or is there another preferred way, how the AbcTopComponent (which acts as an editor) shall access its AbcDataObject? Shall I pass the DataObject as constructor argument to the TopComponent or shall I use a setter method or is there another preferred way?"

Well, the answer to the above question is: "That depends." There are two approaches. Do you want a singleton TopComponent or do you want a different instance of the TopComponent per instance of the DataObject? Look at the screenshot below, where the file underlying the "Car" node is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<car type="Pontiac" color="blue">
<shape_ref file = "wheel.xml"/>
<shape_ref file = "door.xml"/>
</car>

When the user selects "Car", I have a singleton TopComponent that displays the "type" and "color" attributes:

So, when the user selects a different car, the same singleton TopComponent is used:

However, maybe you do not like this approach at all. Maybe you'd like there to be different instances of the TopComponent for each car, which means that multiple cars would be editable simultaneously.

Here is my OpenSupport class for the first scenario, i.e., I want a singleton TopComponent (the other approach is described in the tutorial, yes, either pass into the constructor or use a setter method):

public class CarOpenSupport extends OpenSupport implements OpenCookie, CloseCookie {
public CarOpenSupport(CarDataObject.Entry entry) {
super(entry);
}
@Override
protected CloneableTopComponent createCloneableTopComponent() {
return CarDesignTopComponent.findInstance();
}
}

And, in my TopComponent, here is the "findInstance" method referred to above:

private static CarDesignTopComponent instance;
public static CarDesignTopComponent findInstance(){
if(instance==null){
instance = new CarDesignTopComponent();
return instance;
}
return instance;
}

OK, so now we have a single instance of the TopComponent. Now, in the TopComponent, we listen for the DataObject, which is automatically exposed whenever the user selects a different car:

private Result<CarDataObject> result = null;
@Override
public void resultChanged(LookupEvent le) {
Collection<? extends CarDataObject> allCarNodes = result.allInstances();
if (!allCarNodes.isEmpty()) {
CarDataObject carDataObject = result.allInstances().iterator().next();
FileObject file = carDataObject.getPrimaryFile();
displayTypeAndColor(file);
}
}
@Override
public void componentOpened() {
result = Utilities.actionsGlobalContext().lookupResult(CarDataObject.class);
result.addLookupListener(this);
resultChanged(new LookupEvent(result));
}
@Override
public void componentClosed() {
result.removeLookupListener(this);
}

And here's the "displayTypeAndColor" method, taken straight from the NetBeans XML Editor Extension Module Tutorial:

private void displayTypeAndColor(FileObject file) {
try {
//Get the InputStream of the file:
InputStream is = file.getInputStream();
//Use the NetBeans org.openide.xml.XMLUtil class to create an org.w3c.dom.Document:
Document doc = XMLUtil.parse(new InputSource(is), true, true, null, null);
//Create a list of nodes, for all the elements:
NodeList list = doc.getElementsByTagName("\*");
//Iterate through the list:
for (int i = 0; i < list.getLength(); i++) {
//For each node in the list, create a org.w3c.dom.Node:
org.w3c.dom.Node mainNode = list.item(i);
//Get the name of the node:
String nodeName = mainNode.getNodeName();
if (nodeName.equals("car")) {
//Create a map for all the attributes of the org.w3c.dom.Node:
NamedNodeMap map = mainNode.getAttributes();
//Iterate through the map of attributes:
for (int j = 0; j < map.getLength(); j++) {
//Each iteration, create a new Node:
org.w3c.dom.Node attrNode = map.item(j);
//Get the name of the current Attribute:
String attrName = attrNode.getNodeName();
if (attrName.equals("color")) {
colorField.setText(attrNode.getNodeValue());
}
if (attrName.equals("type")) {
typeField.setText(attrNode.getNodeValue());
//Set the text in the tab of the TopComponent:
setDisplayName("Car: " + attrNode.getNodeValue());
}
}
}
}
is.close();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} catch (SAXException ex) {
Exceptions.printStackTrace(ex);
}
}

Probably the above could be done without the iterations, by simply identifying the required node name and attribute names.

Next time, we'll persist changes in the TopComponent back to the file.

Join the discussion

Comments ( 1 )
  • Tom Saturday, January 26, 2013

    Hello Geertjan,

    Is it possible to use JAXB bindings (generated from XSD) in NetBeans Application?

    Instead writing code in displayTypeAndColor maybe you could just unmarshall it, IMHO it will be much more readable and you would have opportunity to validate XML documents with XSD.

    Currently I've tried to create JAXB bindings in NB Platform app/module but it's not possible (in Ant and Maven build) - in normal Java application it works fine.

    Why I can't do it in NB Platform App, do you have any tips how to integrate JAXB with NB Platform App?

    I've got also second question about Maven Support in NetBeans. Is there going to be something like "Library wrapper module" in Maven project? I have commercial libraries (IBM JDBC Drivers), and I really don't want to create maven repository for few libraries, but my app requires it to work correctly.

    It looks like last commend was not posted.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services