Paul Bininda – Blog
27Aug/09

Subdocument in Netbeans RCP

In my current Netbeans RCP project, I manage entities called configurations which are persisted in a separate component. Each configuration is defined by an XML file and a bunch of additional resource files. The configuration itself (the XML file) can be edited graphically.

A new requirement came up which essentially defined a new type of additional resource files. These resource files contain Lua scripts and have to be editable in the configuration tool.

When the configuration tool opens a configuration, it receives a zip file from the persistence component and extracts the zip file into a memory file system.

The lua scripts can be opened in the standard Netbeans editor component and are handled by a lua editing module. When the configuration is saved, the xml file is saved and the memory file system is zipped and passed to the persistence module.

Two of the challenges where:

  1. When the lua script is modified in the editor, the whole configuration has to be marked as modified as well, since it needs to be saved back again to the persistence module.
  2. When saving a configuration, all edited lua scripts have to be saved automatically before the zip file can be created and sent to the persistence component.

First of all, I implemented a method that finds out if any modified DataObjects exist that are part of a given configuration DataObject.

    public Set<DataObject> getModifiedLuaDataObjects()
    {
        Set<DataObject> modified = 
            DataObject.getRegistry().getModifiedSet();
        final Map<FileObject, DataObject> modifiedFiles = 
            new HashMap<FileObject, DataObject>();
        final Set<DataObject> modifiedDataObjects = 
            new HashSet<DataObject>();
        for (DataObject d: modified)
        {
            modifiedFiles.put (d.getPrimaryFile(), d);
        }
        getConfiguration().walk(new IModelWalker() {

            public boolean visit(StructureItem item) {
                try {
                    URL configFile = item.getConfigurationFile();
                    if (configFile != null)
                    {
                        FileObject fo = 
                            URLMapper.findFileObject(configFile);
                        if (modifiedFiles.containsKey(fo))
                        {
                            modifiedDataObjects.add (modifiedFiles.get(fo));
                        }
                    }
                    return false;
                } catch (Exception e) {
                    Exceptions.printStackTrace(e);
                    return false;
                }
            }
        });
        return modifiedDataObjects;
    }

Then I registered a listener in the DataObject Registry, that gets called, whenever a DataObject changes its modifcation status

    public ConfigurationDataObjectBase
        (final FileObject pf, UniFileLoader loader) 
    throws DataObjectExistsException, IOException
    {
        super (pf, loader);
        //...
        DataObject.getRegistry().
            addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e)
            {
                Set<DataObject> modified = getModifiedLuaDataObjects();
                if (!modified.isEmpty())
                {
                    setModified(true);
                }
            }
        });
    }

When saving a configuration, the following piece of code gets called:

            //...
            Set<DataObject> dataObjects = getModifiedLuaDataObjects();
            for (DataObject dao: dataObjects)
            {
                SaveCookie sc = dao.getCookie(SaveCookie.class);
                if (sc != null)
                {
                    try
                    {
                        sc.save();
                    } catch (IOException ex)
                    {
                        Exceptions.printStackTrace(ex);
                    }
                }
            }
            //...

When a configuration is close, all the open editors for the lua scripts have to be closed as well

    private void closeLuaEditors()
    {
        Set<TopComponent> comps = 
            new HashSet<TopComponent> 
                (TopComponent.getRegistry().getOpened());
        FileObject directory = getPrimaryFile().getParent();
        if (comps != null)
        {
            for (TopComponent tc: comps) {
                Node[] arr = tc.getActivatedNodes();
                if (arr != null)
                {
                    for (Node n: arr)
                    {
                        if (n instanceof DataNode)
                        {
                            DataNode dn = (DataNode) n;
                            FileObject luaFile =
                                dn.getDataObject().getPrimaryFile();
                            if (luaFile.getParent() == directory)
                            {
                                // in same directory as our primary file
                                EditorCookie ec = 
                                    n.getCookie(EditorCookie.class);
                                if (ec != null) {
                                    ec.close();
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.