2323
2424import com .intellij .CommonBundle ;
2525import com .intellij .ide .BrowserUtil ;
26- import com .intellij .openapi .application .ApplicationManager ;
27- import com .intellij .openapi .application .ModalityState ;
2826import com .intellij .openapi .project .Project ;
2927import com .intellij .openapi .ui .DialogWrapper ;
30- import com .microsoft .azure .hdinsight .common .ClusterManagerEx ;
31- import com .microsoft .azure .hdinsight .sdk .cluster .HDInsightAdditionalClusterDetail ;
32- import com .microsoft .azure .hdinsight .sdk .common .AuthenticationException ;
33- import com .microsoft .azure .hdinsight .sdk .storage .HDStorageAccount ;
28+ import com .microsoft .azure .hdinsight .serverexplore .AddNewClusterCtrlProvider ;
29+ import com .microsoft .azure .hdinsight .serverexplore .AddNewClusterModel ;
3430import com .microsoft .azure .hdinsight .serverexplore .hdinsightnode .HDInsightRootModule ;
35- import com .microsoft .azure .hdinsight .spark .jobs .JobUtils ;
36- import com .microsoft .azuretools .azurecommons .helpers .AzureCmdException ;
37- import com .microsoft .azuretools .azurecommons .helpers .StringHelper ;
31+ import com .microsoft .azure .hdinsight .spark .common .SettableControl ;
3832import com .microsoft .azuretools .telemetry .AppInsightsClient ;
3933import com .microsoft .intellij .hdinsight .messages .HDInsightBundle ;
40- import com .microsoft .tooling . msservices . helpers . azure . sdk . StorageClientSDKManager ;
34+ import com .microsoft .intellij . rxjava . IdeaSchedulers ;
4135import com .microsoft .tooling .msservices .model .storage .BlobContainer ;
42- import com .microsoft .tooling .msservices .model .storage .ClientStorageAccount ;
4336import org .apache .commons .lang .StringUtils ;
4437import org .jetbrains .annotations .NotNull ;
4538import org .jetbrains .annotations .Nullable ;
4639
4740import javax .swing .*;
48- import java .awt .*;
4941import java .awt .event .ActionEvent ;
5042import java .awt .event .FocusAdapter ;
5143import java .awt .event .FocusEvent ;
52- import java .util .Optional ;
53- import java .util .stream .Stream ;
54-
55- public class AddNewClusterFrom extends DialogWrapper {
44+ import java .util .stream .Collectors ;
45+ import java .util .stream .IntStream ;
5646
47+ public class AddNewClusterFrom extends DialogWrapper implements SettableControl <AddNewClusterModel >{
48+ @ Nullable
5749 private Project project ;
58- private String clusterName ;
59- private String userName ;
60- private String password ;
61-
62- private String storageName ;
63- private String storageKey ;
64- private String storageContainer ;
65-
66- private HDStorageAccount storageAccount ;
67-
68- private String errorMessage ;
69- private boolean isCarryOnNextStep ;
7050
7151 private JPanel addNewClusterPanel ;
7252 private JTextField clusterNameFiled ;
@@ -83,17 +63,18 @@ public class AddNewClusterFrom extends DialogWrapper {
8363 private JComboBox <BlobContainer > containersComboBox ;
8464 private JLabel storageContainerLabel ;
8565
66+ @ NotNull
8667 private HDInsightRootModule hdInsightModule ;
8768
88- private static final String URL_PREFIX = "https://" ;
8969 private static final String HELP_URL = "https://go.microsoft.com/fwlink/?linkid=866472" ;
9070
91- public AddNewClusterFrom (final Project project , HDInsightRootModule hdInsightModule ) {
71+ public AddNewClusterFrom (@ Nullable final Project project , @ NotNull HDInsightRootModule hdInsightModule ) {
9272 super (project , true );
73+ this .project = project ;
74+
9375 myHelpAction = new HelpAction ();
9476
9577 init ();
96- this .project = project ;
9778 this .hdInsightModule = hdInsightModule ;
9879
9980 this .setTitle ("Link A New HDInsight Cluster" );
@@ -106,43 +87,71 @@ public AddNewClusterFrom(final Project project, HDInsightRootModule hdInsightMod
10687 storageKeyTextField .addFocusListener (new FocusAdapter () {
10788 @ Override
10889 public void focusLost (FocusEvent e ) {
109- super .focusLost (e );
110-
111- if (StringUtils .isNotBlank (storageNameField .getText ()) && StringUtils .isNotBlank (storageKeyTextField .getText ())) {
112- ClientStorageAccount storageAccount = new ClientStorageAccount (storageNameField .getText ());
113- storageAccount .setPrimaryKey (storageKeyTextField .getText ());
114-
115- refreshContainers (storageAccount );
116- }
90+ refreshContainers ();
11791 }
11892 });
11993
12094 storageNameField .addFocusListener (new FocusAdapter () {
12195 @ Override
12296 public void focusLost (FocusEvent e ) {
123- super .focusLost (e );
124-
125- if (StringUtils .isNotBlank (storageNameField .getText ()) && StringUtils .isNotBlank (storageKeyTextField .getText ())) {
126- ClientStorageAccount storageAccount = new ClientStorageAccount (storageNameField .getText ());
127- storageAccount .setPrimaryKey (storageKeyTextField .getText ());
128-
129- refreshContainers (storageAccount );
130- }
97+ refreshContainers ();
13198 }
13299 });
133100 }
134101
135- private void refreshContainers (@ NotNull ClientStorageAccount storageAccount ) {
136- try {
137- containersComboBox .removeAllItems ();
102+ private AddNewClusterCtrlProvider prepareCtrl () {
103+ AddNewClusterModel current = new AddNewClusterModel ();
138104
139- StorageClientSDKManager .getManager ().getBlobContainers (storageAccount .getConnectionString ())
140- .forEach (containersComboBox ::addItem );
105+ getData (current );
106+
107+ return new AddNewClusterCtrlProvider (current );
108+ }
109+
110+ private void refreshContainers () {
111+ prepareCtrl ()
112+ .refreshContainers ()
113+ .subscribeOn (IdeaSchedulers .processBarVisibleAsync (this .project , "Getting storage account containers..." ))
114+ .subscribe (this ::setData );
115+ }
116+
117+ @ Override
118+ public void setData (@ NotNull AddNewClusterModel data ) {
119+ // Data -> Components
120+
121+ // Text fields
122+ clusterNameFiled .setText (data .getClusterName ());
123+ clusterNameLabel .setText (data .getClusterNameLabelTitle ());
124+ userNameField .setText (data .getUserName ());
125+ userNameLabel .setText (data .getUserNameLabelTitle ());
126+ passwordField .setText (data .getPassword ());
127+ passwordLabel .setText (data .getPasswordLabelTitle ());
128+ storageNameField .setText (data .getStorageName ());
129+ storageKeyTextField .setText (data .getStorageKey ());
130+ errorMessageField .setText (data .getErrorMessage ());
131+
132+ // Combo box
133+ containersComboBox .removeAllItems ();
134+ data .getContainers ().forEach (containersComboBox ::addItem );
135+ containersComboBox .setSelectedItem (data .getSelectedContainer ());
136+ }
137+
138+ @ Override
139+ public void getData (@ NotNull AddNewClusterModel data ) {
140+ // Components -> Data
141+ data .setClusterName (clusterNameFiled .getText ())
142+ .setClusterNameLabelTitle (clusterNameLabel .getText ())
143+ .setUserName (userNameField .getText ())
144+ .setUserNameLabelTitle (userNameLabel .getText ())
145+ .setPassword (String .valueOf (passwordField .getPassword ()))
146+ .setPasswordLabelTitle (passwordLabel .getText ())
147+ .setStorageName (storageNameField .getText ())
148+ .setStorageKey (storageKeyTextField .getText ())
149+ .setErrorMessage (errorMessageField .getText ())
150+ .setSelectedContainer ((BlobContainer ) containersComboBox .getSelectedItem ())
151+ .setContainers (IntStream .range (0 , containersComboBox .getItemCount ())
152+ .mapToObj (i -> containersComboBox .getItemAt (i ))
153+ .collect (Collectors .toList ()));
141154
142- containersComboBox .setMaximumRowCount (6 );
143- } catch (AzureCmdException e ) {
144- containersComboBox .removeAllItems ();
145- }
146155 }
147156
148157 private class HelpAction extends AbstractAction {
@@ -162,114 +171,19 @@ protected void doHelpAction() {
162171
163172 @ Override
164173 protected void doOKAction () {
165- synchronized (AddNewClusterFrom .class ) {
166- isCarryOnNextStep = true ;
167- errorMessage = null ;
168- errorMessageField .setVisible (false );
169-
170- String clusterNameOrUrl = clusterNameFiled .getText ().trim ();
171- userName = userNameField .getText ().trim ();
172- storageName = storageNameField .getText ().trim ();
173-
174- storageKey = storageKeyTextField .getText ().trim ();
175-
176- password = String .valueOf (passwordField .getPassword ());
177-
178- AppInsightsClient .create (HDInsightBundle .message ("HDInsightAddNewClusterAction" ), null );
179-
180- if (StringHelper .isNullOrWhiteSpace (clusterNameOrUrl ) || StringHelper .isNullOrWhiteSpace (storageName ) || StringHelper .isNullOrWhiteSpace (storageKey ) || StringHelper .isNullOrWhiteSpace (userName ) || StringHelper .isNullOrWhiteSpace (password )) {
181- Stream <JLabel > highLightLabels = Stream .of (
182- clusterNameLabel ,
183- storageNameLabel ,
184- storageKeyLabel ,
185- storageContainerLabel ,
186- userNameLabel ,
187- passwordLabel );
188-
189- String highlightPrefix = "* " ;
190- highLightLabels .filter (label -> !label .getText ().startsWith (highlightPrefix ))
191- .forEach (label -> label .setText (highlightPrefix + label .getText ()));
192-
193- errorMessage = "All (*) fields are required." ;
194- isCarryOnNextStep = false ;
195- } else {
196- clusterName = getClusterName (clusterNameOrUrl );
197-
198- if (clusterName == null ) {
199- errorMessage = "Wrong cluster name or endpoint" ;
200- isCarryOnNextStep = false ;
201- } else {
202- int status = ClusterManagerEx .getInstance ().isHDInsightAdditionalStorageExist (clusterName , storageName );
203- if (status == 1 ) {
204- errorMessage = "Cluster already exists in linked list" ;
205- isCarryOnNextStep = false ;
206- } else if (status == 2 ) {
207- errorMessage = "Default storage account is required" ;
208- isCarryOnNextStep = false ;
209- }
210- }
211-
212- if (containersComboBox .getSelectedItem () == null ) {
213- errorMessage = "The storage container isn't selected" ;
214- isCarryOnNextStep = false ;
215- } else {
216- storageContainer = ((BlobContainer ) containersComboBox .getSelectedItem ()).getName ();
217- }
218- }
219-
220- if (isCarryOnNextStep ) {
221- getStorageAccount ();
222-
223- if (storageAccount == null ) {
224- isCarryOnNextStep = false ;
225- } else {
226- HDInsightAdditionalClusterDetail hdInsightAdditionalClusterDetail = new HDInsightAdditionalClusterDetail (clusterName , userName , password , storageAccount );
227- try {
228- JobUtils .authenticate (hdInsightAdditionalClusterDetail );
229-
230- ClusterManagerEx .getInstance ().addHDInsightAdditionalCluster (hdInsightAdditionalClusterDetail );
231- hdInsightModule .refreshWithoutAsync ();
232- } catch (AuthenticationException authErr ) {
233- isCarryOnNextStep = false ;
234- errorMessage = "Authentication Error: " + Optional .ofNullable (authErr .getMessage ())
235- .filter (msg -> !msg .isEmpty ())
236- .orElse ("Wrong username/password" ) +
237- " (" + authErr .getErrorCode () + ")" ;
238- } catch (Exception ex ) {
239- isCarryOnNextStep = false ;
240- errorMessage = "Authentication Error: " + ex .getMessage ();
241- }
242- }
243- }
244-
245- if (isCarryOnNextStep ) {
246- super .doOKAction ();
247- } else {
248- errorMessageField .setText (errorMessage );
249- errorMessageField .setVisible (true );
250- }
251- }
252- }
253-
254- //format input string
255- private static String getClusterName (String userNameOrUrl ) {
256- if (userNameOrUrl .startsWith (URL_PREFIX )) {
257- return StringHelper .getClusterNameFromEndPoint (userNameOrUrl );
258- } else {
259- return userNameOrUrl ;
260- }
261- }
262-
263- private void getStorageAccount () {
264- addNewClusterPanel .setCursor (Cursor .getPredefinedCursor (Cursor .WAIT_CURSOR ));
265-
266- ApplicationManager .getApplication ().invokeAndWait (() -> {
267- storageAccount = new HDStorageAccount (
268- null , ClusterManagerEx .getInstance ().getBlobFullName (storageName ), storageKey , false , storageContainer );
269- isCarryOnNextStep = true ;
270- }, ModalityState .NON_MODAL );
271-
272- addNewClusterPanel .setCursor (Cursor .getDefaultCursor ());
174+ prepareCtrl ()
175+ .validateAndAdd ()
176+ .subscribeOn (IdeaSchedulers .processBarVisibleAsync (this .project , "Validating the cluster settings..." ))
177+ .doOnNext (this ::setData )
178+ .map (AddNewClusterModel ::getErrorMessage )
179+ .filter (StringUtils ::isEmpty )
180+ .observeOn (IdeaSchedulers .dispatchThread ()) // UI operation needs to be in dispatch thread
181+ .subscribe (toUpdate -> {
182+ hdInsightModule .refreshWithoutAsync ();
183+ AppInsightsClient .create (HDInsightBundle .message ("HDInsightAddNewClusterAction" ), null );
184+
185+ super .doOKAction ();
186+ });
273187 }
274188
275189 @ NotNull
0 commit comments