站内搜索: 请输入搜索关键词
当前页面: 在线文档首页 > NetBeans API Javadoc (Current Development Version)

Refactoring API - NetBeans Architecture Questions - NetBeans API Javadoc (Current Development Version)

NetBeans Architecture Answers for Refactoring API module

WARNING: answering questions version 1.24 rather than the current 1.29.

Interfaces table

Group of java interfaces
Interface NameIn/OutStabilitySpecified in What Document?
RefactoringAPIExportedUnder Development
RefactoringSPIExportedUnder Development
FilesystemsAPIImportedOfficial .../openide/filesystems/doc-files/api.html

.../openide/filesystems/doc-files/api.html

FileObject

LookupAPIImportedOfficial .../org/openide/util/doc-files/api.html

UtilitiesAPIImportedOfficial .../org/openide/util/doc-files/api.html

NodesAPIImportedOfficial .../overview-summary.html

WindowSystemAPIImportedOfficial .../overview-summary.html

ProjectAPIImportedUnder Development

Project API

TextAPIImportedOfficial

DialogsAPIImportedOfficial

Dialogs API

ActionsAPIImportedOfficial

Actions API

ProgressAPIImportedOfficial

Progress API

UIUtilitiesAPIImportedOfficial

UI Utilities API

DiffAPIImportedOfficial

Diff API

JavaHelpImportedOfficial

JavaHelp

GuardedSectionsImportedOfficial

Guarded Sections

GeneralQueriesAPIImportedOfficial

General Queries API

Group of property interfaces
Interface NameIn/OutStabilitySpecified in What Document?
JavaSourceAPIImportedUnder Development

TreePathHandle

ActionMapKeysImportedStable

the usages window defines jumpNext and jumpPrev action handlers in its ActionMap.

Group of lookup interfaces
Interface NameIn/OutStabilitySpecified in What Document?
org.netbeans.api.javahelp.HelpImportedOfficial
org.netbeans.modules.refactoring.spi.RefactoringPluginFactoryExportedUnder Development
org.netbeans.modules.refactoring.spi.GuardedBlockHandlerFactoryExportedUnder Development
org.netbeans.modules.refactoring.spi.ReadOnlyFilesHandlerExportedUnder Development
org.netbeans.modules.refactoring.spi.ui.ActionsImplementationProviderExportedUnder Development
org.netbeans.modules.refactoring.spi.ui.TreeElementFactoryImplementationExportedUnder Development

Group of layer interfaces
Interface NameIn/OutStabilitySpecified in What Document?
MenuImportedOfficial
ShortcutsImportedOfficial
ActionsImportedOfficial
Loaders-ActionsImportedOfficial

Loaders/folder/any/Actions


General Information

    Question (arch-what): What is this project good for?

    Answer:

    Refactoring module allows developer to do high level code transformations aka refactorings.

    Question (arch-overall): Describe the overall architecture.

    Answer: The Refactoring API module provides UI and API framework for easy and uniform implementation of refactoring features. The Refactoring module provides:
    • API, which allows clients to invoke refactorings programmatically.
    • Plug-in SPI that allows other clients to participate in existing refactorings. E.g. Java Refactoring module implements refactoring features for java files, while J2EE module adds refactoring capability for deployment descriptors
    • API for definition of new Refactorings and pluging them into Refactoring framework

    Question (arch-usecases): Describe the main use cases of the new API. Who will use it under what circumstances? What kind of code would typically need to be written to use the module?

    Answer: Refactoring module provides API for refactorings. The idea is that at least the most elementary set of refactorings should be available via an API, so that the refactorings could be invoked programmatically. This is particulary useful when creating more complex refactorings. These can then be composed from the primitive refactorings accessible via an API using delegation. As an example we can use a simple rename refactoring. When renaming a class in a J2SE environment, simple rename refactoring (which renames all occurrences of the class) is sufficient. However in a J2EE environment, renaming a class may require renaming of other classes to preserve the functionality of the application (e.g. synchrinized renaming a home and remote interface for an EJB). This could be achieved by creating a more complex rename refactoring composed of two simple rename refactorings (one for each class to be renamed).

    When analyzing flow of various refactorings, we have found out that the steps in the flow are very common for all refactorings. The flow is as follows:
    • User selects an object (or set of objects) and chooses to invoke a particular refactoring on it.
    • Refactoring pre-conditions are checked - whether a given refactoring can be invoked on a given object (or set of objects) or not. User needs to be presented with errors (if any). The errors can be fatal or non-fatal. If an error is fatal, it means the refactoring cannot be performed, if it is not fatal, user should be notified of the problem but still be able to proceed with the refactoring.
    • User sets parameters of the refactoring - each refactoring has some input parameters (e.g. new name for an element in case of Rename refactoring). These parameters need to be set by the client.
    • Entered values of refactoring parameters are checked - errors (if any) are presented to the user.
    • Refactoring collects all changes that need to be performed and presents them to the user.
    • User can choose to not perform a particular set of proposed changes.
    • Refactoring is performed - all the changes confirmed by user are made to the source code.
    To make the implementation of various refactorings consistent, the refactoring module provides an API and UI framework that allows these refactorings to be plugged in. This framework enforces the above flow. Using this framework (set of SPI and API) the refactoring implementor can focus purely on the things specific to that particular refactoring (specific pre-conditions checks, parameters checks, implementation of changes, etc.) and leave the functionality that is common for all refactorings (implementation of the flow) up to the framework.

    It is quite common that some modules need to be able to affect the behavior of a refactoring. There are 4 typical use-cases when this is desirable:
    1. A module wants to implement refactoring features for their own elements. For instance Java Refactoring module wants to implement Refactoring for Java elements.
    2. A module wants to participate in existing refactoring. E.g. refactoring of java files requires refactoring of non-java files in J2EE area. When a code is refactored, these non-java files need to be refactored too. We can mention JSP files or deployment descriptors as an example.
    3. A module introduces some hidden relationships between several elements. E.g. a single logical EJB consists of several physical classes. When one of these classes are refactored, the other classes need to be refactored as well.
    4. A module generates some derived code into the guarded blocks. In such case it is desirable that the provider of the guarded block refactors the guarded code, since the refactoring module itself has no knowledge of where the guarded code comes from.
    The refactoring module provides hooks for other modules - an SPI that allows other modules to participate in refactorings. The modules can participate on all refactoring phases from "preCheck" (checking preconditions), through "checkParameters" (checking validity of refactoring parameters) to "prepare" (collecting changes). Use-cases number 1), 2) and 3) are covered by the same SPI (interfaces RefactoringPluginFactory and RefactoringPlugin). The forth use-case (guarded blocks) are covered by a separate set of interfaces, since for this use-case the module does not need to participate in all refactoring phases. The refactoring framework itself automatically detects that a given change points to a code in guarded blocks and requests all registered guarded block providers to handle that situation.

    The rest of this section provides simple orientational examples of API/SPI usage.

    Refactoring API can be used for programmatical invocation of refactorings and for pluging ui for these refactorings in.

    Refactoring API Example:

    Intention: Programatically rename java filecom/company/Test.java to com/company/RenamedTest.java and update references.
    
      	FileObject fo = ...com/company/Test.java...
            RefactoringSession renameSession = RefactoringSession.create("Rename Class");
            refactoring = new RenameRefactoring(fo);
            Problem pre = refactoring.preCheck();
            if (pre!=null && pre.isFatal()) {
         	  //fatal problem in precheck
         	  return;
            }
            refactoring.setNewName("RenamedTest");
            Problem p = refactoring.prepare(renameSession);
            
            if (p!=null && p.isFatal()) {
         	  //fatal problem in precheck
         	  return;
            }
            
            renameSession.doRefactoring(true /* saveAll */);
    

    Refactoring SPI permit other modules to plug into existing refactorings and allow them to participate. Client of SPI must implement factory class RefactoringPluginFactory and register this class into Lookup.

    Refactoring SPI Example 1:

    Intention: Create a plugin for RenameRefactoring, which will participate in existing refactoring (let say in java refactoring) and renames references in XML files.

    //implementation of factory class
    public class J2EERefactoringFactory implements RefactoringPluginFactory {
        
        public RefactoringPlugin createInstance(AbstractRefactoring refactoring) {
        
            if (refactoring instanceof RenameRefactoring) {
                //return our custom instance for RenameRefactoring
                if (wantToParticipate(refactoring.getRefactoredObject())
                    return new J2EERenameRefactoringPlugin((RenameRefactoring) refactoring);
            }
            
            if (refactoring instanceof ... {
                ...
            }
    
            return null;
        }
        
    }
    
    It is necessary to register J2EERefactoringFactory in the lookup:
    META-INF/services/org.netbeans.modules.refactoring.spi.RefactoringPluginFactory
    

    and implement RefactoringPlugin interface:

    //implementation of RefactoringPlugin
    public class J2EERenameRefactoringPlugin implements RefactoringPlugin {
        
        private RenameRefactoring refactoring;
        
        public J2EERenameRefactoringPlugin(RenameRefactoring refactoring) { 
            this.refactoring = refactoring;
        }
     
        public Problem preCheck() {
            ...
        }
        
        public Problem checkParameters() {
            ...
        }
        
        public Problem fastCheckParameters() {
            ...
        }
        
        public void cancelRequest() {
            ...
        }
        
        public Problem prepare(RefactoringElementsBag refactoringElements) {
            RenameRefactoring renameRefactor = ((RenameRefactoring)refactoring);
            Object element = renameRefactor.getRefactoredObject();
            if (...) {
               ...
               //lets add our RefactoringElements for usages found in XML files 
               refactoringElements.add(refactoring, new XMLRenameRefactoringElement());
            }
            return null;
        }
    
        public class XMLRenameRefactoringElement implements RefactoringElementImplementation {
    
            public void performChange() {
                //do change
            }
        }
    
    Refactoring SPI Example 2: Intention: Create a module, which will add Rename... to html files First you must create your ActionsImplementationProvider:
    public class MyProvider extends ActionsImplementationProvider {
        
      public boolean canRename(Lookup lookup) {
        Node[] nodes = lookup.lookupAll(Node.class);
        if (..one node selected and the node belongs to html...)
          return true;
        else 
          return fals;
     }
    
      public Runnable renameImpl(Lookup selectedNodes) {
        Node[] nodes = lookup.lookupAll(Node.class);
        final FileObject fo = getFileFromNode(nodes[0]);
        return new Runnable() {
          public void run() {
            UI.openRefactoringUI(new RenameRefactoringUI(fo);
          }
        }    
      }
    }
    
    And of course your own RefactoringPlugin and RefactoringPluginFactory see Refactoring SPI Example 1 and Refactoring SPI Example 2
    Refactoring SPI Example 3 Module wants to implement it's own refactoring preview tree: Register your own TreeElementFactoryImplementation into META-INF/services if you want to build your own RefactoringPreview tree. For instance Java Refactoring understand Java - specific objects e.g. Projects, Groups, Methods etc.
    public TreeElement getTreeElement(Object o) {
    .
    .
    if (o instanceof SourceGroup) {
      return new SourceGroupTreeElement((SourceGroup)o);
    } else if (o instanceof SomethingFromJava) {
       return new SomethingFromJavaTreeElement((SomethingFromJava) o);
    }
    
    TreeElement is then displayed in refactoring preview panel.


    Other usecases are docummented in javadoc.
    • Module wants to add common Refactoring Action into popup.
      See RefactoringActionsFactory
    • http://wiki.netbeans.org/wiki/view/RefactoringFAQ

    Question (arch-time): What are the time estimates of the work?

    Answer:

    Target Milestone for this task is NetBeans 6.0Dev, M7

    Question (arch-quality): How will the quality of your code be tested and how are future regressions going to be prevented?

    Answer:

    Refactoring module functionality will be covered by Refactoring Unit tests.

    Question (arch-where): Where one can find sources for your module?

    Answer:

    The sources for the module are in NetBeans CVS in refactoring/api directory.


Project and platform dependencies


Deployment

    Question (deploy-jar): Do you deploy just module JAR file(s) or other files as well?

    Answer:

    We deploy only one file: module JAR.

    Question (deploy-nbm): Can you deploy an NBM via the Update Center?

    Answer:

    Yes

    Question (deploy-shared): Do you need to be installed in the shared location only, or in the user directory only, or can your module be installed anywhere?

    Answer:

    The module can be installed anywhere.

    Question (deploy-packages): Are packages of your module made inaccessible by not declaring them public?

    Answer: The only public packages are
    • org.netbeans.modules.refactoring.api
    • org.netbeans.modules.refactoring.api.ui
    • org.netbeans.modules.refactoring.spi
    • org.netbeans.modules.refactoring.spi.ui

    Question (deploy-dependencies): What do other modules need to do to declare a dependency on this one, in addition to or instead of the normal module dependency declaration (e.g. tokens to require)?

    Answer: Nothing.

Compatibility with environment

    Question (compat-i18n): Is your module correctly internationalized?

    Answer:

    Yes

    Question (compat-standards): Does the module implement or define any standards? Is the implementation exact or does it deviate somehow?

    Answer:

    Refactoring module exposes RefactoringAPI and RefactoringSPI

    Question (compat-version): Can your module coexist with earlier and future versions of itself? Can you correctly read all old settings? Will future versions be able to read your current settings? Can you read or politely ignore settings stored by a future version?

    Answer:

    Refactoring module does not load or save any settings.

    Question (compat-deprecation): How the introduction of your project influences functionality provided by previous version of the product?

    Answer:

    XXX no answer for compat-deprecation


Access to resources

    Question (resources-file): Does your module use java.io.File directly?

    Answer:

    No

    Question (resources-layer): Does your module provide own layer? Does it create any files or folders in it? What it is trying to communicate by that and with which components?

    Answer: Refactoring module registers following items:
    • Menu items into Menu folder
    • Shrtcuts into Shortcuts folder
    • Actions into Actions folder
    • DataObject's Actions (Loaders-Actions - Loaders/folder/any/Actions
    • New file Services/org-netbeans-modules-refactoring/options which is used for storing settings of checkbox 'Preview All' and 'Search In Comments'

    Question (resources-read): Does your module read any resources from layers? For what purpose?

    Answer:

    We read contents of Menu/Refactoring in order to provide the same popup menu.

    Question (resources-mask): Does your module mask/hide/override any resources provided by other modules in their layers?

    Answer:

    We hide regular RenameAction (in Loaders/folder/any/Actions)

    Question (resources-preferences): Does your module uses preferences via Preferences API? Does your module use NbPreferences or or regular JDK Preferences ? Does it read, write or both ? Does it share preferences with other modules ? If so, then why ?

    Answer:

    XXX no answer for resources-preferences


Lookup of components


Execution Environment

    Question (exec-property): Is execution of your code influenced by any environment or Java system (System.getProperty) property? On a similar note, is there something interesting that you pass to java.util.logging.Logger? Or do you observe what others log?

    Answer:

    No

    Question (exec-component): Is execution of your code influenced by any (string) property of any of your components?

    Answer:

    ActionMapKeys - the usages window defines jumpNext and jumpPrev action handlers in its ActionMap.

    Question (exec-ant-tasks): Do you define or register any ant tasks that other can use?

    Answer:

    XXX no answer for exec-ant-tasks

    Question (exec-classloader): Does your code create its own class loader(s)?

    Answer:

    No.

    Question (exec-reflection): Does your code use Java Reflection to execute other code?

    Answer:

    No

    Question (exec-privateaccess): Are you aware of any other parts of the system calling some of your methods by reflection?

    Answer:

    No

    Question (exec-process): Do you execute an external process from your module? How do you ensure that the result is the same on different platforms? Do you parse output? Do you depend on result code?

    Answer:

    No

    Question (exec-introspection): Does your module use any kind of runtime type information (instanceof, work with java.lang.Class, etc.)?

    Answer:

    Yes. Introspection is important part of Refactoring API. Refactoring API itself works in many cases just with "Objects" not knowing the type of object. API users are required to implement Refactorings only for objects, which are known to them.

    Question (exec-threading): What threading models, if any, does your module adhere to? How the project behaves with respect to threading?

    Answer:

    Refactoring adhere threading model of java/source module.

    Question (security-policy): Does your functionality require modifications to the standard policy file?

    Answer:

    No

    Question (security-grant): Does your code grant additional rights to some other code?

    Answer:

    No


Format of files and protocols

    Question (format-types): Which protocols and file formats (if any) does your module read or write on disk, or transmit or receive over the network? Do you generate an ant build script? Can it be edited and modified?

    Answer:

    N/A

    Question (format-dnd): Which protocols (if any) does your code understand during Drag & Drop?

    Answer:

    We don't override Node.drag. We have our own ClipboardConvertor. See above.

    Question (format-clipboard): Which data flavors (if any) does your code read from or insert to the clipboard (by access to clipboard on means calling methods on java.awt.datatransfer.Transferable?

    Answer:

    We register our own ClipboardConvertor and we wrap each refactorable Node Transferables with Refactoring Transferables in order to handle move/cut/copy actions as refactoring actions.


Performance and Scalability

    Question (perf-startup): Does your module run any code on startup?

    Answer:

    No.

    Question (perf-exit): Does your module run any code on exit?

    Answer:

    No

    Question (perf-scale): Which external criteria influence the performance of your program (size of file in editor, number of files in menu, in source directory, etc.) and how well your code scales?

    Answer:

    Not known.

    Question (perf-limit): Are there any hard-coded or practical limits in the number or size of elements your code can handle?

    Answer:

    No.

    Question (perf-mem): How much memory does your component consume? Estimate with a relation to the number of windows, etc.

    Answer:

    I don't know.

    Question (perf-wakeup): Does any piece of your code wake up periodically and do something even when the system is otherwise idle (no user interaction)?

    Answer:

    No

    Question (perf-progress): Does your module execute any long-running tasks?

    Answer:

    Yes. Collecting usages is long-running task. It is properly indicated by progress bar and does not lock AWT thread.

    Question (perf-huge_dialogs): Does your module contain any dialogs or wizards with a large number of GUI controls such as combo boxes, lists, trees, or text areas?

    Answer:

    Yes. RefactoringPanel (Output window with tree of found usages can contain big number of found references).

    Question (perf-menus): Does your module use dynamically updated context menus, or context-sensitive actions with complicated and slow enablement logic?

    Answer:

    No

    Question (perf-spi): How the performance of the plugged in code will be enforced?

    Answer:

    SPI will be well documented.


Built on May 28 2007.  |  Portions Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.