Commits

Jan Lahoda committed f08f3b2

BatchApply works somehow again.

Comments (0)

Files changed (12)

api/nbproject/project.xml

                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>org.netbeans.modules.java.platform</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.12</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.netbeans.modules.java.source</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>

api/src/org/netbeans/modules/jackpot30/impl/Utilities.java

 import com.sun.source.tree.Tree;
 import com.sun.source.tree.Tree.Kind;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 import org.netbeans.api.java.source.TreeMaker;
 import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.modules.jackpot30.spi.HintDescription;
 import org.openide.util.NbCollections;
 
 /**
         }
     }
 
+    public static Map<String, Collection<HintDescription>> sortOutHints(Iterable<? extends HintDescription> hints, Map<String, Collection<HintDescription>> output) {
+        for (HintDescription d : hints) {
+            Collection<HintDescription> h = output.get(d.getDisplayName());
+
+            if (h == null) {
+                output.put(d.getDisplayName(), h = new LinkedList<HintDescription>());
+            }
+
+            h.add(d);
+        }
+
+        return output;
+    }
+
 }

api/src/org/netbeans/modules/jackpot30/impl/batch/BatchApply.java

 
 import com.sun.source.tree.CompilationUnitTree;
 import com.sun.source.tree.ImportTree;
+import com.sun.source.tree.Tree.Kind;
 import com.sun.source.util.TreePath;
 import java.awt.Dialog;
 import java.awt.event.ActionEvent;
 import javax.swing.SwingUtilities;
 import javax.swing.text.Document;
 import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.java.platform.JavaPlatform;
+import org.netbeans.api.java.platform.JavaPlatformManager;
 import org.netbeans.api.java.source.ClasspathInfo;
 import org.netbeans.api.java.source.CompilationController;
 import org.netbeans.api.java.source.JavaSource;
 import org.netbeans.api.project.SourceGroup;
 import org.netbeans.api.project.Sources;
 //import org.netbeans.modules.jackpot30.hints.pm.AnnotationBasedHintsRunner;
+import org.netbeans.modules.jackpot30.impl.RulesManager;
+import org.netbeans.modules.jackpot30.impl.hints.HintsInvoker;
+import org.netbeans.modules.jackpot30.impl.pm.BulkSearch;
+import org.netbeans.modules.jackpot30.impl.pm.BulkSearch.BulkPattern;
+import org.netbeans.modules.jackpot30.spi.HintDescription;
+import org.netbeans.modules.jackpot30.spi.HintDescription.PatternDescription;
 import org.netbeans.modules.jackpot30.spi.JavaFix;
 import org.netbeans.modules.java.editor.semantic.SemanticHighlighter;
 import org.netbeans.modules.java.hints.errors.SuppressWarningsFixer;
 import org.netbeans.modules.java.hints.infrastructure.HintsTask;
-import org.netbeans.modules.java.hints.infrastructure.RulesManager;
 import org.netbeans.modules.java.hints.options.HintsSettings;
 import org.netbeans.modules.java.hints.spi.AbstractHint;
 import org.netbeans.modules.java.hints.spi.AbstractHint.HintSeverity;
 import org.netbeans.modules.java.hints.spi.TreeRule;
 import org.netbeans.spi.editor.hints.ErrorDescription;
 import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
 import org.openide.DialogDescriptor;
 import org.openide.DialogDisplayer;
 import org.openide.LifecycleManager;
 
     private static final RequestProcessor WORKER = new RequestProcessor("Batch Hint Apply");
     
-    public static String applyFixes(final Lookup context, final String enabledHints, boolean progress) {
+    public static String applyFixes(final Lookup context, final List<HintDescription> hints, boolean progress) {
         assert !progress || SwingUtilities.isEventDispatchThread();
 
         if (progress) {
                 Runnable exec = new Runnable() {
 
                     public void run() {
-                        result[0] = applyFixesImpl(context, enabledHints, handle, cancel);
+                        result[0] = applyFixesImpl(context, hints, handle, cancel);
 
                         SwingUtilities.invokeLater(new Runnable() {
                             public void run() {
                 handle.finish();
             }
         } else {
-            return applyFixesImpl(context, enabledHints, null, new AtomicBoolean());
+            return applyFixesImpl(context, hints, null, new AtomicBoolean());
         }
     }
 
-    private static String applyFixesImpl(Lookup context, String enabledHints, ProgressHandle h, AtomicBoolean cancel) {
+    private static final ClassPath EMPTY = ClassPathSupport.createClassPath(new FileObject[0]);
+    
+    private static BulkPattern prepareBulkPattern(final Collection<? extends String> patterns) {
+        JavaPlatform select = JavaPlatform.getDefault();
+
+        for (JavaPlatform p : JavaPlatformManager.getDefault().getInstalledPlatforms()) {
+            if (p.getSpecification().getVersion().compareTo(select.getSpecification().getVersion()) > 0) {
+                select = p;
+            }
+        }
+
+        ClasspathInfo cpInfo = ClasspathInfo.create(select.getBootstrapLibraries(), EMPTY, EMPTY);
+        JavaSource js = JavaSource.create(cpInfo);
+        final BulkPattern[] bp = new BulkPattern[1];
+
+        try {
+            js.runUserActionTask(new Task<CompilationController>() {
+                public void run(CompilationController cc) throws Exception {
+                    bp[0] = BulkSearch.create(cc, patterns);
+                }
+            }, true);
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
+
+        return bp[0];
+    }
+
+    private static String applyFixesImpl(Lookup context, List<HintDescription> hints, ProgressHandle h, AtomicBoolean cancel) {
         ProgressHandleWrapper handle = new ProgressHandleWrapper(h, new int[] {20, 40, 40});
 
-        Pattern hints = Pattern.compile(enabledHints);
+        final Map<PatternDescription, List<HintDescription>> patterns = new HashMap<PatternDescription, List<HintDescription>>();
+
+        RulesManager.sortOut(hints, new HashMap<Kind, List<HintDescription>>(), patterns);
+        
+        final Map<String, List<PatternDescription>> patternTests = HintsInvoker.computePatternTests(patterns);
+
+        BulkPattern bp = prepareBulkPattern(patternTests.keySet());
         List<ErrorDescription> eds = new LinkedList<ErrorDescription>();
         Collection<FileObject> toProcess = toProcess(context);
 
         for (Entry<ClasspathInfo, Collection<FileObject>> e: sortedFiles.entrySet()) {
             if (cancel.get()) return null;
             
-            eds.addAll(processFiles(e.getKey(), e.getValue(), hints, handle, cancel));
+            eds.addAll(processFiles(e.getKey(), e.getValue(), bp, patterns, patternTests, handle, cancel));
         }
 
         Map<ErrorDescription, Fix> fixes = new IdentityHashMap<ErrorDescription, Fix>();
         return null;
     }
 
-    private static List<ErrorDescription> processFiles(ClasspathInfo cpInfo, Collection<FileObject> toProcess, final Pattern hints, final ProgressHandleWrapper handle, final AtomicBoolean cancel) {
+    private static List<ErrorDescription> processFiles(ClasspathInfo cpInfo, Collection<FileObject> toProcess, final BulkPattern bulkPattern, final Map<PatternDescription, List<HintDescription>> patterns, final Map<String, List<PatternDescription>> patternTests, final ProgressHandleWrapper handle, final AtomicBoolean cancel) {
         final List<ErrorDescription> eds = new LinkedList<ErrorDescription>();
         //XXX: workarounding NB issues #154252 and #152534:
         for (FileObject file : toProcess) {
 //                    Document doc = ec.openDocument();
 
                     try {
+                        if (cc.toPhase(JavaSource.Phase.PARSED).compareTo(JavaSource.Phase.PARSED) < 0) {
+                            return;
+                        }
+
+                        Set<String> matchingPatterns = BulkSearch.match(cc, cc.getCompilationUnit(), bulkPattern);
+
+                        if (matchingPatterns.isEmpty()) {
+                            return ;
+                        }
+
                         if (cc.toPhase(JavaSource.Phase.RESOLVED).compareTo(JavaSource.Phase.RESOLVED) < 0) {
                             return;
                         }
 
-                        //XXX:
-//                        eds.addAll(new AnnotationBasedHintsRunner().findWarnings(cc, hints));
+                        eds.addAll(new HintsInvoker().doComputeHints(cc, matchingPatterns, patternTests, patterns));
                     } finally {
                         HintsSettings.setPreferencesOverride(null);
                     }
         }
     }
 
-    private static Map<String, Preferences> prepareOverlay(Set<String> enabledHints) {
-        Map<String, Preferences> preferencesOverlay = new HashMap<String, Preferences>();
-        for (List<TreeRule> rules : RulesManager.getInstance().getHints().values()) {
-            for (TreeRule r : rules) {
-                String id = r.getId();
-
-                if (r instanceof AbstractHint && !preferencesOverlay.containsKey(id)) {
-                    OverridePreferences prefs = new OverridePreferences(((AbstractHint) r).getPreferences(null));
-
-                    preferencesOverlay.put(r.getId(), prefs);
-                    HintsSettings.setEnabled(prefs, enabledHints.contains(id));
-                    HintsSettings.setSeverity(prefs, HintSeverity.WARNING);
-                }
-            }
-        }
-
-        return preferencesOverlay;
-    }
-
-    private static class OverridePreferences extends AbstractPreferences {
-
-        private Preferences delegateTo;
-        private Map<String, String> data;
-        private Set<String> removed;
-
-        public OverridePreferences(Preferences delegateTo) {
-            super(null, "");
-            this.data = new HashMap<String, String>();
-            this.removed = new HashSet<String>();
-        }
-
-        protected void putSpi(String key, String value) {
-            data.put(key, value);
-            removed.remove(key);
-        }
-
-        protected String getSpi(String key) {
-            if (data.containsKey(key)) {
-                return data.get(key);
-            } else {
-                if (removed.contains(key)) {
-                    return null;
-                } else {
-                    return delegateTo.get(key, null);
-                }
-            }
-        }
-
-        protected void removeSpi(String key) {
-            removed.add(key);
-        }
-
-        protected void removeNodeSpi() throws BackingStoreException {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        protected String[] keysSpi() throws BackingStoreException {
-            Set<String> keys = new HashSet<String>(Arrays.asList(delegateTo.keys()));
-
-            keys.removeAll(removed);
-            keys.addAll(data.keySet());
-
-            return keys.toArray(new String[0]);
-        }
-
-        protected String[] childrenNamesSpi() throws BackingStoreException {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        protected AbstractPreferences childSpi(String name) {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        protected void syncSpi() throws BackingStoreException {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        protected void flushSpi() throws BackingStoreException {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-    }
-
     public static Collection<FileObject> toProcess(Lookup l) {
         List<FileObject> result = new LinkedList<FileObject>();
 

api/src/org/netbeans/modules/jackpot30/impl/batch/BatchApplyAction.java

 import java.net.URL;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.Icon;
 import javax.swing.KeyStroke;
 import javax.swing.text.Keymap;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.modules.jackpot30.spi.ClassPathBasedHintProvider;
+import org.netbeans.modules.jackpot30.spi.HintDescription;
+import org.netbeans.modules.jackpot30.spi.HintProvider;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
 import org.openide.DialogDescriptor;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
+import org.openide.NotifyDescriptor.Confirmation;
 import org.openide.awt.Mnemonics;
+import org.openide.filesystems.FileObject;
 import org.openide.util.ContextAwareAction;
 import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
         this.attributes = attributes;
     }
 
+    private List<HintDescription> listAllHints() {
+        List<HintDescription> result = new LinkedList<HintDescription>();
+        
+        for (HintProvider p : Lookup.getDefault().lookupAll(HintProvider.class)) {
+            for (HintDescription hd : p.computeHints()) {
+                if (hd.getTriggerPattern() == null) continue; //TODO: only pattern based hints are currently supported
+                result.add(hd);
+            }
+        }
+
+        Set<ClassPath> cps = new HashSet<ClassPath>();
+
+        for (FileObject file : BatchApply.toProcess(context)) {
+            //TODO: no bootstrap:
+            cps.add(ClassPath.getClassPath(file, ClassPath.COMPILE));
+            cps.add(ClassPath.getClassPath(file, ClassPath.SOURCE));
+        }
+
+        cps.remove(null);
+
+        ClassPath cp = ClassPathSupport.createProxyClassPath(cps.toArray(new ClassPath[cps.size()]));
+
+        for (ClassPathBasedHintProvider p : Lookup.getDefault().lookupAll(ClassPathBasedHintProvider.class)) {
+            result.addAll(p.computeHints(cp));
+        }
+
+        return result;
+    }
+
     public void actionPerformed(ActionEvent e) {
-        String hintToExecute = (String) getValue(HINT);
+        //XXX:
+//        String hintToExecute = (String) getValue(HINT);
 
-        if (hintToExecute == null) {
-            NotifyDescriptor.InputLine nd = new NotifyDescriptor.InputLine("Select Hint (regexp)", "Select Hint");
+        List<HintDescription> hintsToExecute;
+
+//        if (hintToExecute == null) {
+            SelectHint sh = new SelectHint(listAllHints());
+            Confirmation nd = new Confirmation(sh, "Select Hint", NotifyDescriptor.OK_CANCEL_OPTION);
 
             if (DialogDisplayer.getDefault().notify(nd) != DialogDescriptor.OK_OPTION) {
                 return ;
             }
             
-            hintToExecute = nd.getInputText();
-        }
+            hintsToExecute = sh.getSelectedHints();
+//        }
 
-        String error = BatchApply.applyFixes(context, hintToExecute, true);
+        String error = BatchApply.applyFixes(context, hintsToExecute, true);
 
         if (error != null) {
             DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(error, NotifyDescriptor.ERROR_MESSAGE));

api/src/org/netbeans/modules/jackpot30/impl/batch/Bundle.properties

 SD_ApplyTransformations=applies specified transformation(s) on specified project or all opened projects
 SD_ApplyTransformationsProject=projects on which the transformations should be applied
 SelectHint.jLabel1.text=Select Hint:
+SelectHint.addHint.text=>>
+SelectHint.addAllHints.text=>>>
+SelectHint.removeHint.text=<<
+SelectHint.removeAllHints.text=<<<
+SelectHint.selectedHintsLabel.text=Selected Hints
+SelectHint.allHintsLabel.text_1=All Hints:

api/src/org/netbeans/modules/jackpot30/impl/batch/OptionProcessorImpl.java

 //            String[] hints = hintsArg.split(":");
 
             Lookup context = Lookups.fixed((Object[]) projects.toArray(new Project[0]));
-            String error = BatchApply.applyFixes(context, hintsArg, false);
-
-            if (error != null) {
-                env.getErrorStream().println("Cannot apply hints because of: " + error);
-            }
+//            String error = BatchApply.applyFixes(context, hintsArg, false);
+//
+//            if (error != null) {
+//                env.getErrorStream().println("Cannot apply hints because of: " + error);
+//            }
         }
 
         for (Entry<String, List<ClassPath>> cps : classPaths.entrySet()) {

api/src/org/netbeans/modules/jackpot30/impl/batch/SelectHint.form

     <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
     <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,2,8"/>
   </AuxValues>
 
-  <Layout>
-    <DimensionLayout dim="0">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" alignment="0" attributes="0">
-              <EmptySpace max="-2" attributes="0"/>
-              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
-              <EmptySpace max="-2" attributes="0"/>
-              <Component id="jComboBox1" pref="295" max="32767" attributes="0"/>
-              <EmptySpace max="-2" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-    <DimensionLayout dim="1">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" alignment="0" attributes="0">
-              <EmptySpace max="-2" attributes="0"/>
-              <Group type="103" groupAlignment="3" attributes="0">
-                  <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
-                  <Component id="jComboBox1" alignment="3" min="-2" max="-2" attributes="0"/>
-              </Group>
-              <EmptySpace pref="264" max="32767" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-  </Layout>
+  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
   <SubComponents>
-    <Component class="javax.swing.JLabel" name="jLabel1">
+    <Component class="javax.swing.JLabel" name="allHintsLabel">
       <Properties>
         <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="org/netbeans/modules/javahints/batch/Bundle.properties" key="SelectHint.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString(&quot;{key}&quot;)"/>
+          <ResourceString bundle="org/netbeans/modules/jackpot30/impl/batch/Bundle.properties" key="SelectHint.allHintsLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
         </Property>
       </Properties>
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="6" anchor="18" weightX="0.0" weightY="0.0"/>
+        </Constraint>
+      </Constraints>
     </Component>
-    <Component class="javax.swing.JComboBox" name="jComboBox1">
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="0" insetsBottom="0" insetsRight="6" anchor="18" weightX="0.5" weightY="1.0"/>
+        </Constraint>
+      </Constraints>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JList" name="allHints">
+          <Properties>
+            <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
+              <StringArray count="5">
+                <StringItem index="0" value="Item 1"/>
+                <StringItem index="1" value="Item 2"/>
+                <StringItem index="2" value="Item 3"/>
+                <StringItem index="3" value="Item 4"/>
+                <StringItem index="4" value="Item 5"/>
+              </StringArray>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane2">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="2" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="6" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.5" weightY="1.0"/>
+        </Constraint>
+      </Constraints>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JList" name="selectedHints">
+          <Properties>
+            <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
+              <StringArray count="5">
+                <StringItem index="0" value="Item 1"/>
+                <StringItem index="1" value="Item 2"/>
+                <StringItem index="2" value="Item 3"/>
+                <StringItem index="3" value="Item 4"/>
+                <StringItem index="4" value="Item 5"/>
+              </StringArray>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JLabel" name="selectedHintsLabel">
       <Properties>
-        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
-          <StringArray count="4">
-            <StringItem index="0" value="Item 1"/>
-            <StringItem index="1" value="Item 2"/>
-            <StringItem index="2" value="Item 3"/>
-            <StringItem index="3" value="Item 4"/>
-          </StringArray>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/jackpot30/impl/batch/Bundle.properties" key="SelectHint.selectedHintsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
         </Property>
       </Properties>
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
+        </Constraint>
+      </Constraints>
     </Component>
+    <Container class="javax.swing.JPanel" name="jPanel1">
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="5" anchor="10" weightX="0.0" weightY="1.0"/>
+        </Constraint>
+      </Constraints>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JButton" name="addHint">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/batch/Bundle.properties" key="SelectHint.addHint.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addHintActionPerformed"/>
+          </Events>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="6" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JButton" name="addAllHints">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/batch/Bundle.properties" key="SelectHint.addAllHints.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addAllHintsActionPerformed"/>
+          </Events>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="0" insetsBottom="6" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JButton" name="removeHint">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/batch/Bundle.properties" key="SelectHint.removeHint.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeHintActionPerformed"/>
+          </Events>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="0" insetsBottom="6" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JButton" name="removeAllHints">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/batch/Bundle.properties" key="SelectHint.removeAllHints.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeAllHintsActionPerformed"/>
+          </Events>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+      </SubComponents>
+    </Container>
   </SubComponents>
 </Form>

api/src/org/netbeans/modules/jackpot30/impl/batch/SelectHint.java

 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common
  *
  * Contributor(s):
  *
- * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ * Portions Copyrighted 2008-2009 Sun Microsystems, Inc.
  */
 
 /*
 
 package org.netbeans.modules.jackpot30.impl.batch;
 
-import javax.swing.DefaultComboBoxModel;
-import org.netbeans.modules.java.hints.spi.TreeRule;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import javax.swing.DefaultListModel;
+import org.netbeans.modules.jackpot30.impl.Utilities;
+import org.netbeans.modules.jackpot30.spi.HintDescription;
 
 /**
  *
  */
 public class SelectHint extends javax.swing.JPanel {
 
-    /** Creates new form SelectHint */
-    public SelectHint() {
+    private Map<String, Collection<HintDescription>> displayName2Hints;
+    
+    public SelectHint(Collection<? extends HintDescription> hints) {
+        displayName2Hints = Utilities.sortOutHints(hints, new TreeMap<String, Collection<HintDescription>>());
+        
         initComponents();
-        DefaultComboBoxModel model = new DefaultComboBoxModel();
-        //XXX:
-//        for (TreeRule r : BatchApply.listHints()) {
-//            model.addElement(new HintDescriptor(r.getId(), r.getDisplayName()));
-//        }
-        jComboBox1.setModel(model);
+
+        DefaultListModel all = new DefaultListModel();
+        DefaultListModel selected = new DefaultListModel();
+
+        for (String dn : displayName2Hints.keySet()) {
+            all.addElement(dn);
+        }
+
+        allHints.setModel(all);
+        selectedHints.setModel(selected);
     }
 
     /** This method is called from within the constructor to
     @SuppressWarnings("unchecked")
     // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
     private void initComponents() {
+        java.awt.GridBagConstraints gridBagConstraints;
 
-        jLabel1 = new javax.swing.JLabel();
-        jComboBox1 = new javax.swing.JComboBox();
+        allHintsLabel = new javax.swing.JLabel();
+        jScrollPane1 = new javax.swing.JScrollPane();
+        allHints = new javax.swing.JList();
+        jScrollPane2 = new javax.swing.JScrollPane();
+        selectedHints = new javax.swing.JList();
+        selectedHintsLabel = new javax.swing.JLabel();
+        jPanel1 = new javax.swing.JPanel();
+        addHint = new javax.swing.JButton();
+        addAllHints = new javax.swing.JButton();
+        removeHint = new javax.swing.JButton();
+        removeAllHints = new javax.swing.JButton();
 
-        jLabel1.setText(org.openide.util.NbBundle.getBundle(SelectHint.class).getString("SelectHint.jLabel1.text")); // NOI18N
+        setLayout(new java.awt.GridBagLayout());
 
-        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
+        allHintsLabel.setText(org.openide.util.NbBundle.getMessage(SelectHint.class, "SelectHint.allHintsLabel.text_1")); // NOI18N
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 6);
+        add(allHintsLabel, gridBagConstraints);
 
-        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
-        this.setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
-            .add(layout.createSequentialGroup()
-                .addContainerGap()
-                .add(jLabel1)
-                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
-                .add(jComboBox1, 0, 295, Short.MAX_VALUE)
-                .addContainerGap())
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
-            .add(layout.createSequentialGroup()
-                .addContainerGap()
-                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
-                    .add(jLabel1)
-                    .add(jComboBox1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
-                .addContainerGap(264, Short.MAX_VALUE))
-        );
+        allHints.setModel(new javax.swing.AbstractListModel() {
+            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
+            public int getSize() { return strings.length; }
+            public Object getElementAt(int i) { return strings[i]; }
+        });
+        jScrollPane1.setViewportView(allHints);
+
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 1;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.weightx = 0.5;
+        gridBagConstraints.weighty = 1.0;
+        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 6);
+        add(jScrollPane1, gridBagConstraints);
+
+        selectedHints.setModel(new javax.swing.AbstractListModel() {
+            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
+            public int getSize() { return strings.length; }
+            public Object getElementAt(int i) { return strings[i]; }
+        });
+        jScrollPane2.setViewportView(selectedHints);
+
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 2;
+        gridBagConstraints.gridy = 1;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.weightx = 0.5;
+        gridBagConstraints.weighty = 1.0;
+        gridBagConstraints.insets = new java.awt.Insets(6, 6, 0, 0);
+        add(jScrollPane2, gridBagConstraints);
+
+        selectedHintsLabel.setText(org.openide.util.NbBundle.getMessage(SelectHint.class, "SelectHint.selectedHintsLabel.text")); // NOI18N
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 2;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
+        add(selectedHintsLabel, gridBagConstraints);
+
+        jPanel1.setLayout(new java.awt.GridBagLayout());
+
+        addHint.setText(org.openide.util.NbBundle.getMessage(SelectHint.class, "SelectHint.addHint.text")); // NOI18N
+        addHint.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                addHintActionPerformed(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+        gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
+        jPanel1.add(addHint, gridBagConstraints);
+
+        addAllHints.setText(org.openide.util.NbBundle.getMessage(SelectHint.class, "SelectHint.addAllHints.text")); // NOI18N
+        addAllHints.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                addAllHintsActionPerformed(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 1;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+        gridBagConstraints.insets = new java.awt.Insets(6, 0, 6, 0);
+        jPanel1.add(addAllHints, gridBagConstraints);
+
+        removeHint.setText(org.openide.util.NbBundle.getMessage(SelectHint.class, "SelectHint.removeHint.text")); // NOI18N
+        removeHint.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                removeHintActionPerformed(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 2;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+        gridBagConstraints.insets = new java.awt.Insets(6, 0, 6, 0);
+        jPanel1.add(removeHint, gridBagConstraints);
+
+        removeAllHints.setText(org.openide.util.NbBundle.getMessage(SelectHint.class, "SelectHint.removeAllHints.text")); // NOI18N
+        removeAllHints.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                removeAllHintsActionPerformed(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 3;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
+        jPanel1.add(removeAllHints, gridBagConstraints);
+
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 1;
+        gridBagConstraints.gridy = 1;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+        gridBagConstraints.weighty = 1.0;
+        gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 5);
+        add(jPanel1, gridBagConstraints);
     }// </editor-fold>//GEN-END:initComponents
 
+    private void addHintActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addHintActionPerformed
+        for (Object selected : allHints.getSelectedValues()) {
+            ((DefaultListModel) selectedHints.getModel()).addElement(selected);
+            ((DefaultListModel) allHints.getModel()).removeElement(selected);
+        }
+    }//GEN-LAST:event_addHintActionPerformed
 
+    private void addAllHintsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addAllHintsActionPerformed
+        for (Object o : ((DefaultListModel) allHints.getModel()).toArray()) {
+            ((DefaultListModel) selectedHints.getModel()).addElement(o);
+        }
+        ((DefaultListModel) allHints.getModel()).removeAllElements();
+    }//GEN-LAST:event_addAllHintsActionPerformed
+
+    private void removeHintActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeHintActionPerformed
+        for (Object selected : selectedHints.getSelectedValues()) {
+            ((DefaultListModel) allHints.getModel()).addElement(selected);
+            ((DefaultListModel) selectedHints.getModel()).removeElement(selected);
+        }
+    }//GEN-LAST:event_removeHintActionPerformed
+
+    private void removeAllHintsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeAllHintsActionPerformed
+        for (Object o : ((DefaultListModel) selectedHints.getModel()).toArray()) {
+            ((DefaultListModel) allHints.getModel()).addElement(o);
+        }
+        ((DefaultListModel) selectedHints.getModel()).removeAllElements();
+    }//GEN-LAST:event_removeAllHintsActionPerformed
 
     // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JComboBox jComboBox1;
-    private javax.swing.JLabel jLabel1;
+    private javax.swing.JButton addAllHints;
+    private javax.swing.JButton addHint;
+    private javax.swing.JList allHints;
+    private javax.swing.JLabel allHintsLabel;
+    private javax.swing.JPanel jPanel1;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JScrollPane jScrollPane2;
+    private javax.swing.JButton removeAllHints;
+    private javax.swing.JButton removeHint;
+    private javax.swing.JList selectedHints;
+    private javax.swing.JLabel selectedHintsLabel;
     // End of variables declaration//GEN-END:variables
 
-    public HintDescriptor getSelectedHint() {
-        return (HintDescriptor) jComboBox1.getSelectedItem();
+    public List<HintDescription> getSelectedHints() {
+        List<HintDescription> hints = new LinkedList<HintDescription>();
+
+        for (Object dn : ((DefaultListModel) selectedHints.getModel()).toArray()) {
+            hints.addAll(displayName2Hints.get((String) dn));
+        }
+
+        return hints;
     }
     
-    public static final class HintDescriptor {
-
-        private final String id;
-        private final String displayName;
-
-        public HintDescriptor(String id, String displayName) {
-            this.id = id;
-            this.displayName = displayName;
-        }
-
-        public String getId() {
-            return id;
-        }
-
-        @Override
-        public String toString() {
-            return displayName;
-        }
-
-    }
 }

api/src/org/netbeans/modules/jackpot30/impl/hints/HintsInvoker.java

             new ScannerImpl(info, cancel, hints).scan(startAt, errors);
         }
         
+        Map<String, List<PatternDescription>> patternTests = computePatternTests(patternHints);
+
+        BulkPattern bulkPattern = BulkSearch.create(info, patternTests.keySet());
+        Set<String> occurringPatterns = BulkSearch.match(info, info.getCompilationUnit(), bulkPattern);
+        
+        errors.addAll(doComputeHints(info, occurringPatterns, patternTests, startAt, patternHints));
+
+        return errors;
+    }
+
+    public List<ErrorDescription> doComputeHints(CompilationInfo info, Set<String> occurringPatterns, Map<String, List<PatternDescription>> patterns, Map<PatternDescription, List<HintDescription>> patternHints) throws IllegalStateException {
+        return doComputeHints(info, occurringPatterns, patterns, new TreePath(info.getCompilationUnit()), patternHints);
+    }
+
+    public static Map<String, List<PatternDescription>> computePatternTests(Map<PatternDescription, List<HintDescription>> patternHints) {
         Map<String, List<PatternDescription>> patternTests = new HashMap<String, List<PatternDescription>>();
-        
         for (Entry<PatternDescription, List<HintDescription>> e : patternHints.entrySet()) {
             String p = e.getKey().getPattern();
             List<PatternDescription> descs = patternTests.get(p);
-
             if (descs == null) {
                 patternTests.put(p, descs = new LinkedList<PatternDescription>());
             }
-
             descs.add(e.getKey());
         }
-
-        BulkPattern bulkPattern = BulkSearch.create(info, patternTests.keySet());
-        Set<String> occurringPatterns = BulkSearch.match(info, info.getCompilationUnit(), bulkPattern);
-
+        return patternTests;
+    }
+    
+    private List<ErrorDescription> doComputeHints(CompilationInfo info, Set<String> occurringPatterns, Map<String, List<PatternDescription>> patterns, TreePath startAt, Map<PatternDescription, List<HintDescription>> patternHints) throws IllegalStateException {
+        List<ErrorDescription> errors = new LinkedList<ErrorDescription>();
+        
         for (String occ : occurringPatterns) {
-            for (PatternDescription d : patternTests.get(occ)) {
+            for (PatternDescription d : patterns.get(occ)) {
                 Map<String, TypeMirror> constraints = new HashMap<String, TypeMirror>();
 
                 for (Entry<String, String> e : d.getConstraints().entrySet()) {
 
                 for (Entry<TreePath, Pair<Map<String, TreePath>, Map<String, String>>> e : CopyFinder.computeDuplicates(info, patt, startAt, cancel, p.getConstraints()).entrySet()) {
                     HintContext c = new HintContext(info, AbstractHint.HintSeverity.WARNING, e.getKey(), e.getValue().getA(), e.getValue().getB());
-                    
+
                     for (HintDescription hd : patternHints.get(d)) {
                         Collection<? extends ErrorDescription> workerErrors = hd.getWorker().createErrors(c);
 
 
         return errors;
     }
-
+    
 //    public static void computeHints(URI file, ProcessingEnvironment env, CompilationUnitTree cut, RulesManager m) {
 //        Map<Kind, HintDescription> hints = m.getKindBasedHints();
 //

api/src/org/netbeans/modules/jackpot30/impl/pm/BulkSearch.java

         return create(info, Arrays.asList(code));
     }
 
-    public static BulkPattern create(CompilationInfo info, Collection<String> code) {
+    public static BulkPattern create(CompilationInfo info, Collection<? extends String> code) {
         StringBuilder ser = new StringBuilder();
         Tree[] patterns = new Tree[code.size()];
         int i = 0;

api/src/org/netbeans/modules/jackpot30/impl/resources/layer.xml

         </folder>
     </folder>
 
+    <!--XXX:-->
+    <folder name="Menu">
+        <folder name="Refactoring">
+            <file name="org-netbeans-modules-jackpot30-impl-batch-BatchApplyAction.instance"/>
+        </folder>
+    </folder>
+
     <folder name="Editors">
         <folder name="text">
             <folder name="x-java">

api/src/org/netbeans/modules/jackpot30/spi/HintDescription.java

 
     //XXX: should not be public
     public String getDisplayName() {
+        if (displayName == null) {
+            //XXX:
+            return "No Display Name";
+        }
+        
         return displayName;
     }