All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.maven.nodes.AddDependencyPanel Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.maven.nodes;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.tree.TreeSelectionModel;
import org.apache.lucene.search.BooleanQuery;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.StaticResource;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.maven.NbMavenProjectImpl;
import org.netbeans.modules.maven.TextValueCompleter;
import org.netbeans.modules.maven.api.NbMavenProject;
import org.netbeans.modules.maven.api.customizer.support.DelayedDocumentChangeListener;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.indexer.api.NBVersionInfo;
import org.netbeans.modules.maven.indexer.api.QueryField;
import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
import org.netbeans.modules.maven.indexer.api.RepositoryQueries;
import org.netbeans.modules.maven.indexer.api.RepositoryQueries.Result;
import static org.netbeans.modules.maven.nodes.Bundle.*;
import org.netbeans.modules.maven.spi.nodes.MavenNodeFactory;
import org.netbeans.spi.project.ui.LogicalViewProvider;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotificationLineSupport;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.view.BeanTreeView;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.RequestProcessor;
import org.openide.util.Task;
import org.openide.util.TaskListener;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;

/**
 * @author  mkleint
 */
public class AddDependencyPanel extends javax.swing.JPanel {
    private static final @StaticResource String EMPTY_ICON = "org/netbeans/modules/maven/resources/empty.png";
    private static final @StaticResource String WAIT_ICON = "org/netbeans/modules/maven/resources/wait.gif";

    /**
     * Shows the Add Dependency dialog.
     * @param prj a project to add a dependency to
     * @param showDepMan true to show the dependency management panel
     * @param selectedScope an initial scope selection (such as {@code compile})
     * @return groupId + artifactId + version + scope + type + classifier, or null if canceled
     */
    @Messages("TIT_Add_Library=Add Dependency")
    public static @CheckForNull String[] show(Project prj, boolean showDepMan, String selectedScope) {
        NbMavenProject nbproj = prj.getLookup().lookup(NbMavenProject.class);
        AddDependencyPanel pnl = new AddDependencyPanel(nbproj.getMavenProject(), showDepMan, prj);
        pnl.getAccessibleContext().setAccessibleDescription(TIT_Add_Library());
        pnl.setSelectedScope(selectedScope);
        DialogDescriptor dd = new DialogDescriptor(pnl, TIT_Add_Library());
        dd.setClosingOptions(new Object[] {
            pnl.getOkButton(),
            DialogDescriptor.CANCEL_OPTION
        });
        dd.setOptions(new Object[] {
            pnl.getOkButton(),
            DialogDescriptor.CANCEL_OPTION
        });
        pnl.attachDialogDisplayer(dd);
        Object ret = DialogDisplayer.getDefault().notify(dd);
        if (pnl.getOkButton() == ret) {
            return new String[] {
                pnl.getGroupId(),
                pnl.getArtifactId(),
                pnl.getVersion(),
                pnl.getScope(),
                pnl.getType(),
                pnl.getClassifier()
            };
        }
        return null;
    }

    private MavenProject project;
    private Project nbProject;

    private final TextValueCompleter groupCompleter;
    private final TextValueCompleter artifactCompleter;
    private final TextValueCompleter versionCompleter;
    private final JButton okButton;
    private final QueryPanel queryPanel;
    private DMListPanel artifactList;

    private Color defaultVersionC;

    private static final RequestProcessor RP = new RequestProcessor(AddDependencyPanel.class.getName(), 5);
    private static final RequestProcessor RPofOpenListPanel = new RequestProcessor(AddDependencyPanel.OpenListPanel.class.getName(), 1);
    private static final RequestProcessor RPofDMListPanel = new RequestProcessor(AddDependencyPanel.DMListPanel.class.getName(), 1);
    private static final RequestProcessor RPofQueryPanel = new RequestProcessor(AddDependencyPanel.QueryPanel.class.getName(), 10);

    private NotificationLineSupport nls;

    @Messages("BTN_OK=Add")
    private AddDependencyPanel(MavenProject mavenProject, boolean showDepMan, Project prj) {
        this.project = mavenProject;
        this.nbProject = prj;
        initComponents();
        groupCompleter = new TextValueCompleter(Collections.emptyList(), txtGroupId);
        artifactCompleter = new TextValueCompleter(Collections.emptyList(), txtArtifactId);
        versionCompleter = new TextValueCompleter(Collections.emptyList(), txtVersion);
        txtGroupId.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                final String groupId = txtGroupId.getText().trim();
                if (groupId.length() > 0) {
                    artifactCompleter.setLoading(true);
                    RP.post(new Runnable() {
                        @Override
                        public void run() {
                            populateArtifact(groupId);
                        }
                    });
                }
            }
        });

        txtArtifactId.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                final String groupId = txtGroupId.getText().trim();
                final String artifactId = txtArtifactId.getText().trim();
                if (groupId.length() > 0 && artifactId.length() > 0) {
                    versionCompleter.setLoading(true);
                    RP.post(new Runnable() {
                        @Override
                        public void run() {
                            populateVersion(groupId, artifactId);
                        }
                    });
                }
            }
        });

        okButton = new JButton(BTN_OK());

        DocumentListener docList = new DocumentListener() {

            @Override
            public void changedUpdate(DocumentEvent e) {
                checkValidState();
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                checkValidState();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                checkValidState();
            }
        };
        txtGroupId.getDocument().addDocumentListener(docList);
        txtVersion.getDocument().addDocumentListener(docList);
        txtArtifactId.getDocument().addDocumentListener(docList);
        checkValidState();
        groupCompleter.setLoading(true);
        RP.post(new Runnable() {
            @Override
            public void run() {
                Result res = populateGroupId();
                if (res.isPartial()) {
                    //we will ignore any rare occurances of repository being added after the groupId result is 
                    // processed.. this is the only way of ensuring that the completion gets refreshed.
                    res.waitForSkipped();
                    populateGroupId();
                    final String[] vals = new String[2];
                    try {
                        SwingUtilities.invokeAndWait(new Runnable() {
                            @Override
                            public void run() {
                                vals[0] = txtGroupId.getText().trim();
                                vals[1] = txtArtifactId.getText().trim();
                            }
                        });
                        if (vals[0] != null && vals[0].length() > 0) {
                            populateArtifact(vals[0]);
                            if (vals[1] != null && vals[1].length() > 0) {
                                populateVersion(vals[0], vals[1]);
                            }
                        }
                    } catch (InterruptedException ex) {
                        Exceptions.printStackTrace(ex);
                    } catch (InvocationTargetException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                }
            }
        });

        queryPanel = new QueryPanel();
        resultsPanel.add(queryPanel, BorderLayout.CENTER);

        searchField.getDocument().addDocumentListener(
                DelayedDocumentChangeListener.create(
                searchField.getDocument(), queryPanel, 500));

        /*searchField.getDocument().addDocumentListener(new DocumentListener() {

            public void insertUpdate(DocumentEvent e) {
                queryPanel.maybeFind(searchField.getText());
            }

            public void removeUpdate(DocumentEvent e) {
                queryPanel.maybeFind(searchField.getText());
            }

            public void changedUpdate(DocumentEvent e) {
                queryPanel.maybeFind(searchField.getText());
            }
        });*/

        defaultVersionC = txtVersion.getForeground();
        if (showDepMan) {
            artifactList = new DMListPanel(project);
            artifactPanel.add(artifactList, BorderLayout.CENTER);
        } else {
            tabPane.setEnabledAt(2, false);
        }
        chkNbOnly.setVisible(false);
        String packaging = prj.getLookup().lookup(NbMavenProject.class).getPackagingType();
        if (NbMavenProject.TYPE_NBM.equals(packaging) || NbMavenProject.TYPE_NBM_APPLICATION.equals(packaging)) {
            chkNbOnly.setVisible(true);
            chkNbOnly.setSelected(true);
        }

        pnlOpenProjects.add(new OpenListPanel(prj), BorderLayout.CENTER);

    }

    private JButton getOkButton() {
        return okButton;
    }

    private String getGroupId() {
        return txtGroupId.getText().trim();
    }

    private String getArtifactId() {
        return txtArtifactId.getText().trim();
    }

    private String getVersion() {
        String v = txtVersion.getText().trim();
        return v.isEmpty() ? null : v;
    }

    private String getScope() {
        String scope = comScope.getSelectedItem().toString();
        if ("compile".equals(scope)) { //NOI18N
            //compile is the default scope, no need to explicitly define.
            scope = null;
        }
        return scope;
    }

    private String getType() {
        String t = txtType.getText().trim();
        return t.isEmpty() ? null : t;
    }

    private String getClassifier() {
        String c = txtClassifier.getText().trim();
        return c.isEmpty() ? null : c;
    }

    /** For gaining access to DialogDisplayer instance to manage
     * warning messages
     */
    private void attachDialogDisplayer(DialogDescriptor dd) {
        nls = dd.getNotificationLineSupport();
        if (nls == null) {
            nls = dd.createNotificationLineSupport();
        }
    }

    @Override
    public void addNotify() {
        super.addNotify();
        assert nls != null : " The notificationLineSupport was not attached to the panel."; //NOI18N
    }

    private void setSelectedScope(String type) {
        comScope.setSelectedItem(type);
    }

    @Messages ({"MSG_Defined=Dependency with given groupId and artifactId is already defined in project."})
    private void checkValidState() {
        String gId = txtGroupId.getText().trim();
        if (gId.length() <= 0) {
            gId = null;
        }
        String aId = txtArtifactId.getText().trim();
        if (aId.length() <= 0) {
            aId = null;
        }
        String version = txtVersion.getText().trim();
        if (version.length() <= 0) {
            version = null;
        }

        String warn = null;
        boolean dmDefined = tabPane.isEnabledAt(2);
        if (artifactList != null) {
            Color c = defaultVersionC;
            if (dmDefined) {
                if (findConflict(artifactList.getDMDeps(), gId, aId, version, null) == 1) {
                    c = Color.RED;
                    warn = NbBundle.getMessage(AddDependencyPanel.class, "MSG_VersionConflict");
                }
            }
            txtVersion.setForeground(c);
        }
        
        if (project.getDependencies() != null && gId != null && aId != null) {
            //poor mans expression evaluator, it's unlikely that some other expressions would be frequent
            String resolvedGroupId = gId.contains("${project.groupId}") ? gId.replace("${project.groupId}", project.getGroupId()) : gId;
            String resolvedArtifactId = aId.contains("${project.artifactId}") ? aId.replace("${project.artifactId}", project.getArtifactId()) : aId;
            
            for (Dependency dep : project.getDependencies()) {
                if (resolvedGroupId.equals(dep.getGroupId()) && resolvedArtifactId.equals(dep.getArtifactId())) {
                    warn = Bundle.MSG_Defined();
                }
                    
            }
        }
        
        if (nls != null) {
            if (warn != null) {
                nls.setWarningMessage(warn);
            } else {
                nls.clearMessages();
            }
        }

        if (gId == null) {
            okButton.setEnabled(false);
            return;
        }
        if (aId == null) {
            okButton.setEnabled(false);
            return;
        }
        if (version == null && !dmDefined) {
            okButton.setEnabled(false);
            return;
        }

        okButton.setEnabled(true);
    }

    private static Border getNbScrollPaneBorder () {
        Border b = UIManager.getBorder("Nb.ScrollPane.border");
        if (b == null) {
            Color c = UIManager.getColor("controlShadow");
            b = new LineBorder(c != null ? c : Color.GRAY);
        }
        return b;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // //GEN-BEGIN:initComponents
    private void initComponents() {

        lblGroupId = new javax.swing.JLabel();
        txtGroupId = new javax.swing.JTextField();
        lblArtifactId = new javax.swing.JLabel();
        txtArtifactId = new javax.swing.JTextField();
        lblVersion = new javax.swing.JLabel();
        txtVersion = new javax.swing.JTextField();
        lblScope = new javax.swing.JLabel();
        comScope = new javax.swing.JComboBox();
        lblType = new javax.swing.JLabel();
        txtType = new javax.swing.JTextField();
        lblClassifier = new javax.swing.JLabel();
        txtClassifier = new javax.swing.JTextField();
        tabPane = new javax.swing.JTabbedPane();
        searchPanel = new javax.swing.JPanel();
        searchLabel = new javax.swing.JLabel();
        searchField = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        resultsLabel = new javax.swing.JLabel();
        resultsPanel = new javax.swing.JPanel();
        jPanel1 = new javax.swing.JPanel();
        chkNbOnly = new javax.swing.JCheckBox();
        pnlOpen = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        pnlOpenProjects = new javax.swing.JPanel();
        pnlDepMan = new javax.swing.JPanel();
        artifactsLabel = new javax.swing.JLabel();
        artifactPanel = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();

        lblGroupId.setLabelFor(txtGroupId);
        org.openide.awt.Mnemonics.setLocalizedText(lblGroupId, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "LBL_GroupId")); // NOI18N

        lblArtifactId.setLabelFor(txtArtifactId);
        org.openide.awt.Mnemonics.setLocalizedText(lblArtifactId, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "LBL_ArtifactId")); // NOI18N

        lblVersion.setLabelFor(txtVersion);
        org.openide.awt.Mnemonics.setLocalizedText(lblVersion, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "LBL_Version")); // NOI18N

        lblScope.setLabelFor(comScope);
        org.openide.awt.Mnemonics.setLocalizedText(lblScope, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "LBL_Scope")); // NOI18N

        comScope.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "compile", "runtime", "test", "provided" }));

        lblType.setLabelFor(txtType);
        org.openide.awt.Mnemonics.setLocalizedText(lblType, NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.lblType.text")); // NOI18N

        lblClassifier.setLabelFor(txtClassifier);
        org.openide.awt.Mnemonics.setLocalizedText(lblClassifier, NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.lblClassifier.text")); // NOI18N

        searchPanel.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentShown(java.awt.event.ComponentEvent evt) {
                searchPanelComponentShown(evt);
            }
        });

        searchLabel.setLabelFor(searchField);
        org.openide.awt.Mnemonics.setLocalizedText(searchLabel, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.searchLabel.text", new Object[] {})); // NOI18N

        searchField.setText(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.searchField.text", new Object[] {})); // NOI18N

        jLabel1.setForeground(javax.swing.UIManager.getDefaults().getColor("textInactiveText"));
        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.jLabel1.text", new Object[] {})); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(resultsLabel, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.resultsLabel.text", new Object[] {})); // NOI18N

        resultsPanel.setBorder(getNbScrollPaneBorder());
        resultsPanel.setLayout(new java.awt.BorderLayout());

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 76, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 18, Short.MAX_VALUE)
        );

        org.openide.awt.Mnemonics.setLocalizedText(chkNbOnly, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.chkNbOnly.text")); // NOI18N
        chkNbOnly.setToolTipText(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.chkNbOnly.toolTipText")); // NOI18N
        chkNbOnly.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                chkNbOnlyActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel);
        searchPanel.setLayout(searchPanelLayout);
        searchPanelLayout.setHorizontalGroup(
            searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, searchPanelLayout.createSequentialGroup()
                .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(searchPanelLayout.createSequentialGroup()
                        .addGap(12, 12, 12)
                        .addComponent(searchLabel)
                        .addGap(4, 4, 4)
                        .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel1)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, searchPanelLayout.createSequentialGroup()
                                .addComponent(searchField, javax.swing.GroupLayout.DEFAULT_SIZE, 365, Short.MAX_VALUE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(chkNbOnly))))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, searchPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(resultsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 554, Short.MAX_VALUE)
                            .addGroup(searchPanelLayout.createSequentialGroup()
                                .addComponent(resultsLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 261, Short.MAX_VALUE)
                                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(106, 106, 106)))))
                .addContainerGap())
        );
        searchPanelLayout.setVerticalGroup(
            searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(searchPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(searchLabel)
                    .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(chkNbOnly))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(resultsLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(resultsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 198, Short.MAX_VALUE)
                .addContainerGap())
        );

        searchField.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.searchField.AccessibleContext.accessibleDescription")); // NOI18N
        resultsLabel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.resultsLabel.AccessibleContext.accessibleDescription")); // NOI18N

        tabPane.addTab(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.searchPanel.TabConstraints.tabTitle", new Object[] {}), null, searchPanel, NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.searchPanel.TabConstraints.tabToolTip")); // NOI18N

        jLabel3.setLabelFor(pnlOpenProjects);
        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.jLabel3.text")); // NOI18N

        pnlOpenProjects.setLayout(new java.awt.BorderLayout());

        javax.swing.GroupLayout pnlOpenLayout = new javax.swing.GroupLayout(pnlOpen);
        pnlOpen.setLayout(pnlOpenLayout);
        pnlOpenLayout.setHorizontalGroup(
            pnlOpenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlOpenLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlOpenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(pnlOpenProjects, javax.swing.GroupLayout.DEFAULT_SIZE, 554, Short.MAX_VALUE)
                    .addComponent(jLabel3))
                .addContainerGap())
        );
        pnlOpenLayout.setVerticalGroup(
            pnlOpenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlOpenLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnlOpenProjects, javax.swing.GroupLayout.DEFAULT_SIZE, 247, Short.MAX_VALUE)
                .addContainerGap())
        );

        tabPane.addTab(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.pnlOpen.TabConstraints.tabTitle"), null, pnlOpen, NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.pnlOpen.TabConstraints.tabToolTip")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(artifactsLabel, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.artifactsLabel.text", new Object[] {})); // NOI18N

        artifactPanel.setBorder(getNbScrollPaneBorder());
        artifactPanel.setLayout(new java.awt.BorderLayout());

        jLabel2.setForeground(javax.swing.UIManager.getDefaults().getColor("textInactiveText"));
        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.jLabel2.text", new Object[] {})); // NOI18N
        artifactPanel.add(jLabel2, java.awt.BorderLayout.PAGE_END);

        javax.swing.GroupLayout pnlDepManLayout = new javax.swing.GroupLayout(pnlDepMan);
        pnlDepMan.setLayout(pnlDepManLayout);
        pnlDepManLayout.setHorizontalGroup(
            pnlDepManLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlDepManLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlDepManLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(artifactPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 554, Short.MAX_VALUE)
                    .addComponent(artifactsLabel))
                .addContainerGap())
        );
        pnlDepManLayout.setVerticalGroup(
            pnlDepManLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlDepManLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(artifactsLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(artifactPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 247, Short.MAX_VALUE)
                .addContainerGap())
        );

        tabPane.addTab(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.pnlDepMan.TabConstraints.tabTitle", new Object[] {}), null, pnlDepMan, NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.pnlDepMan.TabConstraints.tabToolTip")); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lblGroupId)
                    .addComponent(lblArtifactId)
                    .addComponent(lblVersion)
                    .addComponent(lblType))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(txtArtifactId, javax.swing.GroupLayout.DEFAULT_SIZE, 472, Short.MAX_VALUE)
                    .addComponent(txtGroupId, javax.swing.GroupLayout.DEFAULT_SIZE, 472, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(txtVersion, javax.swing.GroupLayout.DEFAULT_SIZE, 310, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lblScope)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(comScope, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, 169, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lblClassifier)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(txtClassifier, javax.swing.GroupLayout.DEFAULT_SIZE, 208, Short.MAX_VALUE)))
                .addContainerGap())
            .addComponent(tabPane, javax.swing.GroupLayout.DEFAULT_SIZE, 583, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblGroupId)
                    .addComponent(txtGroupId, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblArtifactId)
                    .addComponent(txtArtifactId, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblVersion)
                    .addComponent(txtVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(comScope, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblScope))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblType)
                    .addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblClassifier)
                    .addComponent(txtClassifier, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(tabPane, javax.swing.GroupLayout.DEFAULT_SIZE, 319, Short.MAX_VALUE))
        );

        txtGroupId.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.txtGroupId.AccessibleContext.accessibleDescription")); // NOI18N
        txtArtifactId.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.txtArtifactId.AccessibleContext.accessibleDescription")); // NOI18N
        txtVersion.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.txtVersion.AccessibleContext.accessibleDescription")); // NOI18N
        comScope.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.comScope.AccessibleContext.accessibleDescription")); // NOI18N
        tabPane.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AddDependencyPanel.class, "AddDependencyPanel.tabPane.AccessibleContext.accessibleDescription")); // NOI18N
    }// //GEN-END:initComponents

    private void searchPanelComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_searchPanelComponentShown
        searchField.requestFocus();
    }//GEN-LAST:event_searchPanelComponentShown

    private void chkNbOnlyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkNbOnlyActionPerformed
        queryPanel.stateChanged(new ChangeEvent(searchField.getDocument()));
    }//GEN-LAST:event_chkNbOnlyActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel artifactPanel;
    private javax.swing.JLabel artifactsLabel;
    private javax.swing.JCheckBox chkNbOnly;
    private javax.swing.JComboBox comScope;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JLabel lblArtifactId;
    private javax.swing.JLabel lblClassifier;
    private javax.swing.JLabel lblGroupId;
    private javax.swing.JLabel lblScope;
    private javax.swing.JLabel lblType;
    private javax.swing.JLabel lblVersion;
    private javax.swing.JPanel pnlDepMan;
    private javax.swing.JPanel pnlOpen;
    private javax.swing.JPanel pnlOpenProjects;
    private javax.swing.JLabel resultsLabel;
    private javax.swing.JPanel resultsPanel;
    private javax.swing.JTextField searchField;
    private javax.swing.JLabel searchLabel;
    private javax.swing.JPanel searchPanel;
    private javax.swing.JTabbedPane tabPane;
    private javax.swing.JTextField txtArtifactId;
    private javax.swing.JTextField txtClassifier;
    private javax.swing.JTextField txtGroupId;
    private javax.swing.JTextField txtType;
    private javax.swing.JTextField txtVersion;
    // End of variables declaration//GEN-END:variables
    // End of variables declaration

    private Result populateGroupId() {
        assert !SwingUtilities.isEventDispatchThread();
        final Result result = RepositoryQueries.getGroupsResult(RepositoryPreferences.getInstance().getRepositoryInfos());
        final List lst = new ArrayList(result.getResults());
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                groupCompleter.setValueList(lst, result.isPartial());
            }
        });
        return result;
    }

    private Result populateArtifact(String groupId) {
        assert !SwingUtilities.isEventDispatchThread();
        final Result result = RepositoryQueries.getArtifactsResult(groupId, RepositoryPreferences.getInstance().getRepositoryInfos());
        final List lst = new ArrayList(result.getResults());
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                artifactCompleter.setValueList(lst, result.isPartial());
            }
        });
        return result;
    }

    private Result populateVersion(String groupId, String artifactId) {
        assert !SwingUtilities.isEventDispatchThread();
        final Result result = RepositoryQueries.getVersionsResult(groupId, artifactId, RepositoryPreferences.getInstance().getRepositoryInfos());
        List lst = result.getResults();
        final List vers = new ArrayList();
        for (NBVersionInfo rec : lst) {
            if (!vers.contains(rec.getVersion())) {
                vers.add(rec.getVersion());
            }
        }
        // also include properties/expressions that could be related to version
        // management
        List propList = new ArrayList();
        for (Object propKey : project.getProperties().keySet()) {
            String key = (String)propKey;
            if (key.endsWith(".version")) { //NOI18N
                // is this the correct heuristics?
                propList.add("${" + key + "}");
            }
        }
        Collections.sort(propList);
        vers.addAll(propList);
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                versionCompleter.setValueList(vers, result.isPartial());
            }
        });
        return result;
    }

    private static List getDependenciesFromDM(MavenProject project, Project nbprj) {
        NbMavenProjectImpl p = nbprj.getLookup().lookup(NbMavenProjectImpl.class);
        MavenProject localProj = project;
        DependencyManagement curDM;
        List result = new ArrayList();
        //mkleint: without the managementKey checks I got some entries multiple times.
        // do we actually need to traverse the parent poms, are they completely resolved anyway?
        //XXX
        Set knownKeys = new HashSet();

        while (localProj != null) {
            curDM = localProj.getDependencyManagement();
            if (curDM != null) {
                @SuppressWarnings("unchecked")
                List ds = curDM.getDependencies();
                for (Dependency d : ds) {
                    if (knownKeys.contains(d.getManagementKey())) {
                        continue;
                    }
                    result.add(d);
                    knownKeys.add(d.getManagementKey());
                }
            }
            try {
                localProj = p.loadParentOf(EmbedderFactory.getProjectEmbedder(), localProj);
                if (localProj == null || NbMavenProject.isErrorPlaceholder(localProj)) {
                    break;
                }
            } catch (ProjectBuildingException x) {
                break;
            }
        }
        result.sort(new Comparator() {

            @Override
            public int compare(Dependency o1, Dependency o2) {
                return o1.getManagementKey().compareTo(o2.getManagementKey());
            }
        });
        return result;
    }

    /**
     * @return 0 -> no conflicts, 1 -> conflict in version, 2 -> conflict in scope
     */
    private static int findConflict (List deps, String groupId, String artifactId, String version, String scope) {
        if (deps == null) {
            return 0;
        }
        for (Dependency dep : deps) {
            if (artifactId != null && artifactId.equals(dep.getArtifactId()) &&
                    groupId != null && groupId.equals(dep.getGroupId())) {
                if (version != null && !version.equals(dep.getVersion())) {
                    return 1;
                }
                if (scope != null) {
                    if (!scope.equals(dep.getScope())) {
                        return 2;
                    }
                } else if (dep.getScope() != null) {
                    return 2;
                }

            }
        }

        return 0;
    }

    private void setFields(String groupId, String artifactId, String version, String type, String classifier) {
        boolean sameGrId = false;
        if (groupId != null && groupId.equals(project.getGroupId())) {
            groupId = "${project.groupId}"; //NOI18N
            sameGrId = true;
        }
        txtGroupId.setText(groupId);
        txtArtifactId.setText(artifactId);
        if (sameGrId && version != null && version.equals(project.getVersion())) {
            version = "${project.version}"; //NOI18N
        }
        txtVersion.setText(version);
        if (type != null) {
            if (type.equals("jar") || 
                    (("nbm".equals(project.getPackaging()) || "nbm-application".equals(project.getPackaging())) && type.equals("nbm"))) {//NOI18N
                type = null;
            }
        }
        txtType.setText(type);
        txtClassifier.setText(classifier);
    }

    private static Node noResultsNode, searchingNode, tooGeneralNode;

    private static Node getNoResultsNode() {
        if (noResultsNode == null) {
            AbstractNode nd = new AbstractNode(Children.LEAF) {

                @Override
                public Image getIcon(int arg0) {
                    return ImageUtilities.loadImage(EMPTY_ICON); //NOI18N
                    }

                @Override
                public Image getOpenedIcon(int arg0) {
                    return getIcon(arg0);
                }
            };
            nd.setName("Empty"); //NOI18N

            nd.setDisplayName(NbBundle.getMessage(AddDependencyPanel.class, "LBL_Node_Empty")); //NOI18N

            noResultsNode = nd;
        }

        return new FilterNode (noResultsNode, Children.LEAF);
    }

    private static Node getSearchingNode() {
        if (searchingNode == null) {
            AbstractNode nd = new AbstractNode(Children.LEAF) {

                @Override
                public Image getIcon(int arg0) {
                    return ImageUtilities.loadImage(WAIT_ICON); //NOI18N
                }

                @Override
                public Image getOpenedIcon(int arg0) {
                    return getIcon(arg0);
                }
            };
            nd.setName("Searching"); //NOI18N

            nd.setDisplayName(NbBundle.getMessage(AddDependencyPanel.class, "LBL_Node_Searching")); //NOI18N

            searchingNode = nd;
        }

        return new FilterNode (searchingNode, Children.LEAF);
    }
    
    private static Node getTooGeneralNode() {
        if (tooGeneralNode == null) {
            AbstractNode nd = new AbstractNode(Children.LEAF) {

                @Override
                public Image getIcon(int arg0) {
                    return ImageUtilities.loadImage(EMPTY_ICON); //NOI18N
                    }

                @Override
                public Image getOpenedIcon(int arg0) {
                    return getIcon(arg0);
                }
            };
            nd.setName("Too General"); //NOI18N

            nd.setDisplayName(NbBundle.getMessage(AddDependencyPanel.class, "LBL_Node_TooGeneral")); //NOI18N

            tooGeneralNode = nd;
        }

        return new FilterNode (tooGeneralNode, Children.LEAF);
    }
    
    private class ResultsRootNode extends AbstractNode {

        private ResultsRootChildren resultsChildren;

        public ResultsRootNode() {
            this(new InstanceContent());
        }

        private ResultsRootNode(InstanceContent content) {
            super (new ResultsRootChildren(), new AbstractLookup(content));
            content.add(this);
            this.resultsChildren = (ResultsRootChildren) getChildren();
        }

        public void setOneChild(Node n) {
            List ch = new ArrayList(1);
            ch.add(n);
            setNewChildren(ch);
        }
        
        public void setNewChildren(List ch) {
            resultsChildren.setNewChildren (ch);
        }
    }
    
    private class ResultsRootChildren extends Children.Keys {
        
        List myNodes;

        public ResultsRootChildren() {
            myNodes = Collections.EMPTY_LIST;
        }

        private void setNewChildren(List ch) {
            myNodes = ch;
            refreshList();
        }

        @Override
        protected void addNotify() {
            refreshList();
        }

        private void refreshList() {
            List keys = new ArrayList<>();
            for (Node node : myNodes) {
                keys.add(node);
            }
            setKeys(keys);
        }

        @Override
        protected Node[] createNodes(Node key) {
            return new Node[] { key };
        }

    }

    private static final Object LOCK = new Object();

    private class QueryPanel extends JPanel implements ExplorerManager.Provider,
            Comparator, PropertyChangeListener, ChangeListener {
        

        private final BeanTreeView btv;
        private final ExplorerManager manager;
        private final ResultsRootNode resultsRootNode;

        private String inProgressText, lastQueryText, curTypedText;

        private final Color defSearchC;

        private QueryPanel() {
            btv = new BeanTreeView();
            btv.setRootVisible(false);
            btv.setDefaultActionAllowed(true);
            btv.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
            manager = new ExplorerManager();
            setLayout(new BorderLayout());
            add(btv, BorderLayout.CENTER);
            defSearchC = AddDependencyPanel.this.searchField.getForeground();
            manager.addPropertyChangeListener(this);
            AddDependencyPanel.this.resultsLabel.setLabelFor(btv);
            btv.getAccessibleContext().setAccessibleDescription(AddDependencyPanel.this.resultsLabel.getAccessibleContext().getAccessibleDescription());
            resultsRootNode = new ResultsRootNode();
            manager.setRootContext(resultsRootNode);
        }

        /** delayed change of query text */
        @Override
        public void stateChanged (ChangeEvent e) {
            Document doc = (Document)e.getSource();
            try {
                curTypedText = doc.getText(0, doc.getLength()).trim();
            } catch (BadLocationException ex) {
                // should never happen, nothing we can do probably
                return;
            }

            AddDependencyPanel.this.searchField.setForeground(defSearchC);

            if (curTypedText.length() > 0) {
                find(curTypedText);
            }
        }
        
                private boolean cancel() {
                    synchronized (LOCK) {
                        if (lastQueryText != null && !lastQueryText.equals(inProgressText)) {
                            return true; //we no longer care
                        }
                    }
                    return false;
                }
        

        @Messages({"MSG_ClassesExcluded=Too general query. Class names excluded from the search.",
                   "# {0} - number",
                   "# {1} - total number",
                   "MSG_Narrow=Only {0} of {1} results shown. Consider narrowing your search."
                  })
        void find(String queryText) {
            synchronized (LOCK) {
                if (inProgressText != null) {
                    lastQueryText = queryText;
                    // stop waiting for results of the previous search
                    //TODO we want to have the current task cancelled and new one started.
                    //currently we wait for the first one to finish, which takes forever in some cases.
                    
                    return;
                }
                inProgressText = queryText;
                lastQueryText = null;
            }

            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    resultsRootNode.setOneChild(getSearchingNode());
                    AddDependencyPanel.this.searchField.setForeground(defSearchC);
                    AddDependencyPanel.this.nls.clearMessages();
                }
            });

            final List fields = new ArrayList();
            final List fieldsNonClasses = new ArrayList();
            String q = queryText.trim();
            String[] splits = q.split(" "); //NOI118N

            List fStrings = new ArrayList();
            fStrings.add(QueryField.FIELD_GROUPID);
            fStrings.add(QueryField.FIELD_ARTIFACTID);
            fStrings.add(QueryField.FIELD_VERSION);
            fStrings.add(QueryField.FIELD_NAME);
            fStrings.add(QueryField.FIELD_DESCRIPTION);
            fStrings.add(QueryField.FIELD_CLASSES);

            for (String curText : splits) {
                for (String fld : fStrings) {
                    QueryField f = new QueryField();
                    f.setField(fld);
                    f.setValue(curText);
                    fields.add(f);
                    if (!QueryField.FIELD_CLASSES.equals(fld)) {
                        fieldsNonClasses.add(f);
                    }
                }
            }
            

            Task t = RPofQueryPanel.post(new Runnable() {
                
                @Override
                public void run() {
                    if (cancel()) return;//we no longer care
                    //first try with classes search included,
                    try {
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                AddDependencyPanel.this.nls.setInformationMessage(null); //NOI18N
                            }
                        });
                        final Result result = RepositoryQueries.findResult(fields, RepositoryPreferences.getInstance().getRepositoryInfos());
                        if (cancel()) return;//we no longer care
                        updateResults(result.getResults(), result.isPartial());
                        if (result.isPartial()) {
                            if (cancel()) return;//we no longer care
                            result.waitForSkipped();
                            if (cancel()) return;//we no longer care
                            updateResults(result.getResults(), false);
                        }
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                if (result.getReturnedResultCount() < result.getTotalResultCount()) {
                                    AddDependencyPanel.this.nls.setInformationMessage(MSG_Narrow(result.getReturnedResultCount(), result.getTotalResultCount()));
                                }
                            }
                        });
                        
                    } catch (BooleanQuery.TooManyClauses exc) {
                        if (cancel()) return;//we no longer care
                        // if failing, then exclude classes from search..
                        try {
                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    AddDependencyPanel.this.nls.setInformationMessage(MSG_ClassesExcluded());
                                }
                            });
                            Result result = RepositoryQueries.findResult(fieldsNonClasses, RepositoryPreferences.getInstance().getRepositoryInfos());
                            if (cancel()) return;//we no longer care
                            updateResults(result.getResults(), result.isPartial());
                            if (result.isPartial()) {
                                result.waitForSkipped();
                                if (cancel()) return;//we no longer care
                                updateResults(result.getResults(), false);
                            }
                        } catch (BooleanQuery.TooManyClauses exc2) {
                            // if still failing, report to the user
                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    AddDependencyPanel.this.searchField.setForeground(Color.RED);
                                    AddDependencyPanel.this.nls.setWarningMessage(NbBundle.getMessage(AddDependencyPanel.class, "MSG_TooGeneral")); //NOI18N
                                    resultsRootNode.setOneChild(getTooGeneralNode());
                                }
                            });
                        }
                    } catch (OutOfMemoryError oome) {
                        // running into OOME may still happen in Lucene despite the fact that
                        // we are trying hard to prevent it in NexusRepositoryIndexerImpl
                        // (see #190265)
                        // in the bad circumstances theoretically any thread may encounter OOME
                        // but most probably this thread will be it
                        // trying to indicate the condition to the user here
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                AddDependencyPanel.this.searchField.setForeground(Color.RED);
                                AddDependencyPanel.this.nls.setWarningMessage(NbBundle.getMessage(AddDependencyPanel.class, "MSG_TooGeneral")); //NOI18N
                                resultsRootNode.setOneChild(getTooGeneralNode());
                            }
                        });
                    }
                }
            });

            t.addTaskListener(new TaskListener() {

                @Override
                public void taskFinished(Task task) {
                    synchronized (LOCK) {
                        String localText = inProgressText;
                        inProgressText = null;
                        if (lastQueryText != null && !lastQueryText.equals(localText)) {
                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    if (lastQueryText != null) {
                                        find(lastQueryText);
                                    }
                                }
                            });
                        }
                    }
                }
            });
        }

        @Override
        public ExplorerManager getExplorerManager() {
            return manager;
        }

        void updateResults(List infos, final boolean partial) {
            final Map> map = new HashMap>();

            if (infos != null) {
                if (chkNbOnly.isSelected()) { // #181656: show only NB modules
                    List refined = new ArrayList();
                    Map check = new HashMap(); // class index works only on JAR artifacts
                    Set found = new HashSet(); // but search string might also be found in other fields
                    for (NBVersionInfo nbvi : infos) {
                        String key = key(nbvi);
                        if (NbMavenProject.TYPE_NBM.equals(nbvi.getPackaging())) {
                            refined.add(nbvi);
                            found.add(key);
                        } else {
                            check.put(key, nbvi);
                        }
                    }
                    final Result findResult = RepositoryQueries.getGAVsForPackaging(NbMavenProject.TYPE_NBM, RepositoryPreferences.getInstance().getRepositoryInfos());
                    for (String alt : findResult.getResults()) {
                        if (check.containsKey(alt) && !found.contains(alt)) {
                            refined.add(check.get(alt));
                        }
                    }
                    Collections.sort(refined);
                    infos = refined;
                }
                for (NBVersionInfo nbvi : infos) {
                    String key = nbvi.getGroupId() + " : " + nbvi.getArtifactId(); //NOI18n
                    List get = map.get(key);
                    if (get == null) {
                        get = new ArrayList();
                        map.put(key, get);
                    }
                    get.add(nbvi);
                }
            }

            final List keyList = new ArrayList(map.keySet());
            // sort specially using our comparator, see compare method
            keyList.sort(QueryPanel.this);

            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    updateResultNodes(keyList, map, partial);
                }
            });
        }


        private void updateResultNodes(List keyList, Map> map, boolean partial) {

            if (keyList.size() > 0) { // some results available
                
                Map currentNodes = new HashMap();
                for (Node nd : resultsRootNode.getChildren().getNodes()) {
                    currentNodes.put(nd.getName(), nd);
                }
                List newNodes = new ArrayList(keyList.size());

                    // still searching?
                if (partial)
                    newNodes.add(getSearchingNode());
                
                for (String key : keyList) {
                    Node nd;
                    nd = currentNodes.get(key);
                    if (null != nd) {
                        ((MavenNodeFactory.ArtifactNode)((FilterNodeWithDefAction)nd).getOriginal()).setVersionInfos(map.get(key));
                    } else {
                        nd = createFilterWithDefaultAction(MavenNodeFactory.createArtifactNode(key, map.get(key)), false);
                    }
                    newNodes.add(nd);
                }
                
                resultsRootNode.setNewChildren(newNodes);
            } else if (partial) { // still searching, no results yet
                resultsRootNode.setOneChild(getSearchingNode());
            } else { // finished searching with no results
                resultsRootNode.setOneChild(getNoResultsNode());
            }
        }

        /** Impl of comparator, sorts artifacts asfabetically with exception
         * of items that contain current query string, which take precedence.
         */
        @Override
        public int compare(String s1, String s2) {

            int index1 = s1.indexOf(inProgressText);
            int index2 = s2.indexOf(inProgressText);

            if (index1 >= 0 || index2 >=0) {
                if (index1 < 0) {
                    return 1;
                } else if (index2 < 0) {
                    return -1;
                }
                return s1.compareTo(s2);
            } else {
                return s1.compareTo(s2);
            }
        }

        /** PropertyChangeListener impl, stores maven coordinates of selected artifact */
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) {
                Node[] selNodes = manager.getSelectedNodes();
                changeSelection(selNodes.length == 1 ? selNodes[0].getLookup() : Lookup.EMPTY);
            }
        }

        private String key(NBVersionInfo nbvi) {
            return nbvi.getGroupId() + ':' + nbvi.getArtifactId() + ':' + nbvi.getVersion();
        }

    } // QueryPanel

    private static final Object DM_DEPS_LOCK = new Object();
    private class DMListPanel extends JPanel implements ExplorerManager.Provider,
            AncestorListener, ActionListener, PropertyChangeListener, Runnable {

        private final BeanTreeView btv;
        private final ExplorerManager manager;
        private final MavenProject project;
        private Node noDMRoot;

        private List dmDeps;

        public DMListPanel(MavenProject project) {
            this.project = project;
            btv = new BeanTreeView();
            btv.setRootVisible(false);
            btv.setDefaultActionAllowed(true);
            //lv.setDefaultProcessor(this);
            manager = new ExplorerManager();
            manager.addPropertyChangeListener(this);
            setLayout(new BorderLayout());
            add(btv, BorderLayout.CENTER);
            addAncestorListener(this);
            AddDependencyPanel.this.artifactsLabel.setLabelFor(btv);

            // disable tab if DM section not defined
            RPofDMListPanel.post(this);
        }

        @Override
        public ExplorerManager getExplorerManager() {
            return manager;
        }

        private NBVersionInfo convert2VInfo(Dependency dep) {
            return new NBVersionInfo(null, dep.getGroupId(), dep.getArtifactId(),
                    dep.getVersion(), dep.getType(), null, null, null, dep.getClassifier());
        }

        private List getDMDeps() {
            synchronized (DM_DEPS_LOCK) {
                return dmDeps;
            }
        }

        private void loadArtifacts() {
            List deps = getDMDeps();
            if (deps == null || deps.isEmpty()) {
                if (noDMRoot == null) {
                    AbstractNode nd = new AbstractNode(Children.LEAF) {
                        @Override
                        public Image getIcon(int arg0) {
                            return ImageUtilities.loadImage(EMPTY_ICON); //NOI18N
                        }
                        @Override
                        public Image getOpenedIcon(int arg0) {
                            return getIcon(arg0);
                        }
                    };
                    nd.setName("Empty"); //NOI18N
                    nd.setDisplayName(NbBundle.getMessage(AddDependencyPanel.class, "LBL_DM_Empty"));
                    Children.Array array = new Children.Array();
                    array.add(new Node[]{nd});
                    noDMRoot = new AbstractNode(array);
                }
                manager.setRootContext(noDMRoot);
            } else {
                Children.Array array = new Children.Array();
                Node root = new AbstractNode(array);
                for (Dependency dep : deps) {
                    array.add(new Node[]{ createFilterWithDefaultAction(MavenNodeFactory.createVersionNode(convert2VInfo(dep), true), true) });
                }
                manager.setRootContext(root);
            }
        }

        @Override
        public void ancestorAdded(AncestorEvent event) {
            loadArtifacts();
        }

        @Override
        public void ancestorRemoved(AncestorEvent event) {
        }

        @Override
        public void ancestorMoved(AncestorEvent event) {
        }

        @Override
        public void actionPerformed(ActionEvent e) {
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Node[] selNodes = manager.getSelectedNodes();
            changeSelection(selNodes.length == 1 ? selNodes[0].getLookup() : Lookup.EMPTY);
        }

        /** Loads dependencies outside EQ thread, updates tab state in EQ */
        @Override
        public void run() {
            synchronized (DM_DEPS_LOCK) {
                dmDeps = getDependenciesFromDM(project, AddDependencyPanel.this.nbProject);
            }
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    boolean dmEmpty = dmDeps.isEmpty();
                    tabPane.setEnabledAt(2, !dmEmpty);
                }
            });
        }

    }


    private class OpenListPanel extends JPanel implements ExplorerManager.Provider,
            PropertyChangeListener, Runnable {

        private final BeanTreeView btv;
        private final ExplorerManager manager;
        private final Project project;

        public OpenListPanel(Project project) {
            this.project = project;
            btv = new BeanTreeView();
            btv.setRootVisible(false);
            btv.setDefaultActionAllowed(true);
            manager = new ExplorerManager();
            manager.addPropertyChangeListener(this);
            setLayout(new BorderLayout());
            add(btv, BorderLayout.CENTER);

            RPofOpenListPanel.post(this);
        }

        @Override
        public ExplorerManager getExplorerManager() {
            return manager;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Node[] selNodes = manager.getSelectedNodes();
            changeSelection(selNodes.length == 1 ? selNodes[0].getLookup() : Lookup.EMPTY);
        }

        /** Loads dependencies outside EQ thread, updates tab state in EQ */
        @Override
        public void run() {
            Project[] prjs = OpenProjects.getDefault().getOpenProjects();
            final List toRet = new ArrayList();
            for (Project p : prjs) {
                if (p == project) {
                    continue;
                }
                NbMavenProject mav = p.getLookup().lookup(NbMavenProject.class);
                if (mav != null) {
                    boolean continueProjectIteration = false;
                    MavenProject mavenProject = mav.getMavenProject();
                    Iterator iterator = project.getLookup().lookup(NbMavenProject.class).getMavenProject().getDependencies().iterator();
                    while (iterator.hasNext()) {
                        Dependency dependency = iterator.next();
                        if (mavenProject.getGroupId().equals(dependency.getGroupId())
                                && mavenProject.getArtifactId().equals(dependency.getArtifactId())) {
                            continueProjectIteration = true;
                            break;
                        }
                    }
                    if ( continueProjectIteration ) {
                        continue;
                    }
                    LogicalViewProvider lvp = p.getLookup().lookup(LogicalViewProvider.class);
                    toRet.add(createFilterWithDefaultAction(lvp.createLogicalView(), true));
                }
            }
            Children.Array ch = new Children.Array();
            ch.add(toRet.toArray(new Node[0]));
            Node root = new AbstractNode(ch);
            getExplorerManager().setRootContext(root);
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    boolean opEmpty = toRet.isEmpty();
                    tabPane.setEnabledAt(1, !opEmpty);
                }
            });
        }

    }

    private class DefAction extends AbstractAction implements ContextAwareAction {
        private final boolean close;
        private final Lookup lookup;

        public DefAction(boolean closeNow, Lookup look) {
            this.close = closeNow;
            lookup = look;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Project prj = lookup.lookup(Project.class);
            boolean set = false;
            if (prj != null) {
                NbMavenProject mav = prj.getLookup().lookup(NbMavenProject.class);
                MavenProject m = mav.getMavenProject();
                AddDependencyPanel.this.setFields(m.getGroupId(), m.getArtifactId(), m.getVersion(), null, null);
                set = true;
            }
            if (!set) {
                NBVersionInfo vi = lookup.lookup(NBVersionInfo.class);
                if (vi != null) {
                    //in dm panel we want to pass empty version
                    boolean isDM = lookup.lookup(DependencyManagement.class) != null;
                    String ver =  isDM ?  "" : vi.getVersion();
                    String type = isDM ? "" : vi.getType();
                    String classifier = isDM ? "" : vi.getClassifier();
                    AddDependencyPanel.this.setFields(vi.getGroupId(), vi.getArtifactId(), ver, type, classifier);
                    set = true;
                }
            }
            if (set) {
                if (close) {
                    AddDependencyPanel.this.getOkButton().doClick();
                } else {
                    //reset completion.
                    AddDependencyPanel.this.artifactCompleter.setLoading(true);
                    AddDependencyPanel.this.versionCompleter.setLoading(true);
                    final String groupId = txtGroupId.getText().trim();
                    final String artifactId = txtArtifactId.getText().trim();
                    RP.post(new Runnable() {
                        @Override public void run() {
                            populateArtifact(groupId);
                            populateVersion(groupId, artifactId);
                        }
                    });
                }
            } else {
                AddDependencyPanel.this.setFields("", "", "", "", ""); //NOI18N
                //reset completion.
                AddDependencyPanel.this.artifactCompleter.setValueList(Collections.emptyList(), false);
                AddDependencyPanel.this.versionCompleter.setValueList(Collections.emptyList(), false);
            }
        }

        @Override
        public Action createContextAwareInstance(Lookup actionContext) {
            return new DefAction(close, actionContext);
        }

    }

    private void changeSelection(Lookup context) {
        new DefAction(false, context).actionPerformed(null);
    }

    private Node createFilterWithDefaultAction(final Node nd, boolean leaf) {
        return new FilterNodeWithDefAction (nd, leaf);
    }

    class FilterNodeWithDefAction extends FilterNode {

        public FilterNodeWithDefAction(Node nd, boolean leaf) {
            super(nd, leaf ? Children.LEAF : new FilterNode.Children(nd) {
                @Override
                protected Node[] createNodes(Node key) {
                    return new Node[]{createFilterWithDefaultAction(key, true)};
                }
            });
        }

        @Override
        public Action getPreferredAction() {
            return super.getPreferredAction();
        }

        @Override
        public Action[] getActions(boolean context) {
            return new Action[0];
        }
        
        @Override
        public Node getOriginal() {
            return super.getOriginal();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy