WebResourceRefactoring

Web Resources Refactoring

This document describes the possible solution, how to implement refactoring infrastructure for common refactoring usages. I expect that you have some basic knowledge of the Refactoring API.

Basically the Refactoring API is composed from two part. The first one is "the refactoring infrastructure", which takes care about invoking refactoring actions, refactoring ui dialogs, starting and providing refactoring sessions. The functionality, which provides the changes or finds usages belongs to the second part. The functionality is called refactoring plugins and the plugins are invoked from the refactoring sessions.

So far there is in NetBeans only one refactoring infrastructure - the java. Which means that we are able to write refactoring plugins, which reacts on the changes connected with java file objects and java events.

Web Resource Refactoring Infrastructure

Creating infrastructure through the Refactoring API is based on the File/Data Objects. For example if you want to create refactoring for renaming a jsp file you should basicly do: - Define Rename Refactoring Action in a layer file for the appropriate mimetype. In JSP case it's Loaders/text/x-jsp/Actions folder in default file system. - Register JSP ActionImplementationProvider as a service. The ActionImplementationProvider is a class from Refactoring SPI. The JSP ActionImplementationProvider is called from the refactoring actions. - Create ui for renaming dialog of jsp page

The JSP ActionImplementationProvider is the most important part. Refactoring actions asks to all registered actions providers, whether the action can be enabled in the given context. In our case the JSP Action provider should check, whether a refactoring action was invoked for a jsp file / jsp data object. If yes, then the JSP Action Provider is responsible for creating appropriate dialog (Rename, Find usages ... ) and finally create and start the refactoring session.

Refactoring Plugins

If the actions provider creates and start for example a rename refactoring session, then all refactoring plugins, which are registered through the Refactoring plugin factory, are called. The refactoring plugins are responsible for executing changes. If there will be registerd JSP Refactoring Plugin Factory, then this factory is asked for rename plugin from all refactoring sessions even from java rename refactoring session. The plugin factory is responsible for creating the plugins.

Web Resource Refactoring Infrastructure

From what I wrote above it looks like that if we want to have refactoring for jsp, html, css and other web resources, we need to create refactoring infrastructure for all these file types, which is a lot of work. The solution of this is creating Web Resource Refactoring module which will provide the refactoring infrastructure and probably some refactoring plugins, which provide support for different web resource. Then you should just define that the resource can be refactored.

Example: I want to add refactoring for html files. I don't have to create any java code, just I'm able to add the refactoring infrastructure through the layer file. I need to do:

  1. Define the refactoring actions in the layer file:
    <folder name="Loaders">
        <folder name="text">
            <folder name="html">
                <folder name="Actions">
                      .....
                <file name="html-refactoring-separator-1.instance">
                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator" />
                    </file>
                    <attr boolvalue="true" name="html-refactoring-separator-1.instance/WhereUsedAction.instance" />
                    <file name="WhereUsedAction.instance">
                        <attr name="instanceCreate" methodvalue="org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory.whereUsedAction"/>
                    </file>
                    <attr boolvalue="true" name="WhereUsedAction.instance/RefactoringAll.instance" />
                    <file name="RefactoringAll.instance">
                        <attr name="instanceCreate" methodvalue="org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory.popupSubmenuAction"/>
                    </file>
                    <attr boolvalue="true" name="RefactoringAll.instance/html-refactoring-separator-2.instance" />
                    <file name="html-refactoring-separator-2.instance">
                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator" />
                    </file>
                ......
  1. Define that the Web Resource Refactoring module should take care about the html files too. The definition is again done in the layer file.
    <folder name="WebResourceRefactoring">
        <folder name="Infrastructure">
            <file name="org-netbeans-modules-html-refactoring-mimetypeprofider.instance">
                <attr name="instanceOf" stringvalue="org.netbeans.modules.web.refactoring.spi.SupportedMimeTypeProvider"/>
                <attr name="instanceCreate" methodvalue="org.netbeans.modules.web.refactoring.spi.SupportedMimeType.mimeType"/>
                <attr name="mimetype" stringvalue="text/html"/>
            </file>
        </folder>
    </folder>

There is one interface and one class which are expose in the Web Resource Refactoring SPI. Again other modules don't have to implement them.

public interface SupportedMimeTypeProvider {
    String[] getSupportedMimeTypes();
}
final class SupportedMimeType implements SupportedMimeTypeProvider {
    private String mimetype;
    private SupportedMimeType(String mimetype) {
        this.mimetype = mimetype;
    }

    public static SupportedMimeTypeProvider mimetype(Map<?,?> map) throws Exception {
        Object obj = map.get("mimetype"); // NOI18N
        if (obj instanceof String) {
                SupportedMimeType smt = new SupportedMimeType((String)obj);
                return smt;
        } else {
            throw new IllegalArgumentException("The parameter doesn't contains String: " + obj); // NOI18N
        }
    }

    public String[] getSupportedMimeTypes() {
        return new String[] { mimetype };
    }
}

In the most cases the clients will not need to implement something. They just will define the mimetype through the layer file. On the other hand there is still possibility to write different implementation and used it.

Web Resource Refactoring Plugins

In some cases is not importand whether you are looking for usages of html, jsp or css. The file can be used as a relative or abosule url in other files. So the finding usages it can be done in one refactoring plugin, but the plugin has to know, that it can work with the file. For this puporse you can use again definition through the layer file. The example of html:

     <folder name="WebResourceRefactoring">
        <folder name="RalativeAbsolutePathPlugin">
            <file name="org-netbeans-modules-html-refactoring-mimetypeprofider.instance">
                <attr name="instanceOf" stringvalue="org.netbeans.modules.web.refactoring.spi.SupportedMimeTypeProvider"/>
                <attr name="instanceCreate" methodvalue="org.netbeans.modules.web.refactoring.spi.SupportedMimeType"/>
                <attr name="mimetype" stringvalue="text/html"/>
            </file>
        </folder>
    </folder>

The RelativeAbsolutePath Refactoring not covers all cases, because it's able to work only with relative path between refactored and scanned file and absolute path from document base of the web module. Which is not suitable for example for jsf, because the jsf defines the mappings. For this purpose the jsf module should provide appropriate refactoring plugins.

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo