Revision c4a37180

b/res/layout/addexternalnode.xml
16 16
			android:text="Port"></TextView>
17 17
		<EditText android:layout_width="fill_parent"
18 18
			android:layout_height="wrap_content" android:inputType="number"
19
			android:layout_marginLeft="20dip" android:layout_marginRight="30dip"
20
			android:id="@+id/node_port_text">
19
			android:layout_marginLeft="20dip" android:layout_marginRight="30dip" android:id="@+id/node_port_text">
21 20
			<requestFocus></requestFocus>
22 21
		</EditText>
23 22
		<TextView android:layout_width="wrap_content" android:id="@+id/TextView01"
......
35 34
			android:id="@+id/node_weight_text"></EditText>
36 35
		<Button android:layout_gravity="center_horizontal"
37 36
			android:layout_marginTop="10dip" android:layout_marginBottom="10dip"
38
			android:layout_width="120dip" android:text="Submit" android:id="@+id/add_node_button"
39
			android:layout_height="wrap_content"></Button>
37
			android:layout_width="120dip" android:text="Submit" android:layout_height="wrap_content" android:id="@+id/add_node_button"></Button>
40 38
	</LinearLayout>
41 39

  
42 40
</ScrollView>
b/src/com/rackspacecloud/android/AddExternalNodeActivity.java
3 3
import java.util.regex.Matcher;
4 4
import java.util.regex.Pattern;
5 5

  
6
import com.rackspace.cloud.loadbalancer.api.client.Node;
7

  
6 8
import android.content.Intent;
7 9
import android.os.Bundle;
8 10
import android.view.View;
......
27 29
	private Spinner conditionSpinner;
28 30
	private EditText ipAddress;
29 31
	private EditText weightText;
30

  
32
	private Node node;
33
	
31 34
	public void onCreate(Bundle savedInstanceState) {
32 35
		super.onCreate(savedInstanceState);
33 36
		requestWindowFeature(Window.FEATURE_NO_TITLE);
34 37
		setContentView(R.layout.addexternalnode);
35 38
		weighted = (Boolean) this.getIntent().getExtras().get("weighted");
39
		node = (Node) this.getIntent().getExtras().get("node");
36 40
		restoreState(savedInstanceState);
37 41
	} 
38 42

  
......
42 46
	}
43 47

  
44 48
	private void setupInputs(){
45

  
49
		
46 50
		ipAddress = (EditText) findViewById(R.id.ip_address);
47 51
		
48 52
		weightText = (EditText) findViewById(R.id.node_weight_text);
......
57 61
		loadConditionSpinner();
58 62
		setUpButton();
59 63

  
64
		if(node != null){
65
			ipAddress.setText(node.getAddress());
66
			weightText.setText(node.getWeight());
67
			((EditText)findViewById(R.id.node_port_text)).setText(node.getPort());
68
			conditionSpinner.setSelection(getLocation(CONDITIONS, node.getCondition()));
69
		}
70
	}
71
	
72
	private int getLocation(Object[] objects, Object object){
73
		for(int i = 0; i < objects.length; i++){
74
			if(object.equals(objects[i])){
75
				return i;
76
			}
77
		}
78
		return 0;
60 79
	}
61 80

  
62 81
	private void setUpButton(){
......
75 94
				} else if(ipAddress.getText().toString().equals("")){
76 95
					//TODO use regex to validate the ip for IPV4 and IPV6
77 96
					showAlert("Error", "Enter an IP Address");
78
				} else if(validIp(ipAddress.getText().toString())) {
97
				} else if(!validIp(ipAddress.getText().toString())) {
79 98
					showAlert("Error", "Enter a valid IP Address");
80 99
				} else {
81 100
					Intent data = new Intent();
......
91 110
		});
92 111
	}
93 112

  
94
	public void onBackPressed(){
95
		setResult(RESULT_CANCELED);
96
		finish();
97
	}
98

  
99 113
	private void loadConditionSpinner(){
100 114
		conditionSpinner = (Spinner) findViewById(R.id.node_condition_spinner);
101 115

  
......
128 142
	}
129 143

  
130 144
	private boolean validPort(String port){
131
		return !port.equals("") && Integer.valueOf(port) > 0 && Integer.valueOf(port) < 65536;
145
		boolean result;
146
		try{
147
			result = !port.equals("") && Integer.valueOf(port) > 0 && Integer.valueOf(port) < 65536;
148
		} catch (NumberFormatException e) {
149
	    	result = false;
150
	    }
151
	    return result;
132 152
	}
133 153

  
134 154
	private Boolean validWeight(String weight){
......
136 156
			return false;
137 157
		}
138 158
		else{
139
			int w = Integer.valueOf(weight);
159
			int w;
160
			try{
161
				w = Integer.valueOf(weight);
162
			} catch (NumberFormatException e){
163
				return false;
164
			}
140 165
			return w >= 1 && w <= 100 ;
141 166
		}
142 167
	}
143 168

  
169
	public void onBackPressed(){
170
		setResult(RESULT_CANCELED);
171
		finish();
172
	}
173

  
144 174
}
145 175

  
b/src/com/rackspacecloud/android/AddLoadBalancerActivity.java
12 12
import com.rackspace.cloud.loadbalancer.api.client.VirtualIp;
13 13
import com.rackspace.cloud.servers.api.client.Account;
14 14
import com.rackspace.cloud.servers.api.client.CloudServersException;
15
import com.rackspace.cloud.servers.api.client.Server;
15 16
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
16 17

  
17 18
import android.app.Activity;
......
20 21
import android.os.Bundle;
21 22
import android.text.Editable;
22 23
import android.text.TextWatcher;
24
import android.util.Log;
23 25
import android.view.View;
24 26
import android.view.View.OnClickListener;
25 27
import android.widget.AdapterView;
......
38 40
	private static final int SHARED_VIP_ACTIVITY_CODE = 235;
39 41

  
40 42
	private ArrayList<Node> nodes;
43
	private ArrayList<Server> possibleNodes;
41 44
	private LoadBalancer loadBalancer;
42 45
	private Protocol[] protocols;
43 46
	private Protocol selectedProtocol;
......
74 77
		else{
75 78
			nodes = new ArrayList<Node>();
76 79
		}
80
		
81
		if(state != null && state.containsKey("possibleNodes")){
82
			possibleNodes = (ArrayList<Server>) state.getSerializable("possibleNodes");
83
		}
84
		else{
85
			possibleNodes = new ArrayList<Server>();
86
		}
77 87

  
78 88
		setupText();
79 89
		loadProtocolSpinner();
......
88 98
	protected void onSaveInstanceState(Bundle outState) {
89 99
		super.onSaveInstanceState(outState);
90 100
		outState.putSerializable("nodes", nodes);
101
		outState.putSerializable("possibleNodes", possibleNodes);
91 102
	}
92 103

  
93 104
	public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
......
146 157
			public void onClick(View v) {
147 158
				Intent viewIntent = new Intent(getApplicationContext(), AddNodesActivity.class);
148 159
				viewIntent.putExtra("nodes", nodes);
160
				viewIntent.putExtra("possibleNodes", possibleNodes);
149 161
				startActivityForResult(viewIntent, ADD_NODES_ACTIVITY_CODE);
150 162
			}
151 163
		});
......
159 171
				//selectedPort = ((EditText)findViewById(R.id.edit_port_text)).getText().toString();
160 172
				if(!validName()){
161 173
					showAlert("Error", "Load balancer name cannot be blank.");
162
				} else if(!validPort()){
174
				} else if(!validPort(selectedPort)){
163 175
					showAlert("Error", "Must have a protocol port number that is between 1 and 65535.");
164 176
				} else if(!validVip()){
165 177
					showAlert("Error", "Please select a valid Virtual IP.");
......
189 201
		return !selectedName.equals("");
190 202
	}
191 203

  
192
	private boolean validPort(){
193
		return !selectedPort.equals("") && Integer.valueOf(selectedPort) > 0 && Integer.valueOf(selectedPort) < 65536;
204
	private boolean validPort(String selectedPort){
205
		boolean result;
206
		try{
207
			result = !selectedPort.equals("") && Integer.valueOf(selectedPort) > 0 && Integer.valueOf(selectedPort) < 65536; 
208
		} catch (NumberFormatException e){
209
			result = false;
210
		}
211
		return result;
194 212
	}
195 213

  
196 214
	private boolean validNodes(){
197
		return nodes != null && nodes.size() > 0;
198
	}
199

  
200
	private void updateNodesIndicatorLight(){
201
		if(validNodes()){
202
			selectNodesButton.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0);
203
		} else {
204
			selectNodesButton.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_notification_overlay,0);
215
		boolean exist = nodes != null && nodes.size() > 0;
216
		boolean enabled = false;
217
		for(Node n: nodes){
218
			enabled = enabled || n.getCondition().equalsIgnoreCase("enabled");
205 219
		}
220
		return exist && enabled;
206 221
	}
207 222

  
208 223
	private boolean validVip(){
......
218 233
		||(selectedVip != null && !selectedVip.getLoadBalancer().getPort().equals(selectedPort) 
219 234
				&& selectedVip.getLoadBalancer().getRegion().equals(selectedRegion));
220 235
	}
236
	
237
	private void updateNodesIndicatorLight(){
238
		if(validNodes()){
239
			selectNodesButton.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0);
240
		} else {
241
			selectNodesButton.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_notification_overlay,0);
242
		}
243
	}
221 244

  
222 245
	private void updateVipIndicatorLight(){
223 246
		if(validVip()){
......
310 333

  
311 334
		for(int i = 0; i < Algorithm.getAlgorithms().size(); i++){
312 335
			algorithms[i] = Algorithm.getAlgorithms().get(i);
313
			algorithmNames[i] = Algorithm.getAlgorithms().get(i).getName();
336
			algorithmNames[i] = getPrettyAlgoName(Algorithm.getAlgorithms().get(i).getName());
314 337
		}
315 338

  
316 339
		ArrayAdapter<String> algorithmAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, algorithmNames);
......
318 341
		algorithmSpinner.setAdapter(algorithmAdapter);
319 342
	}
320 343

  
344
	private String getPrettyAlgoName(String name){
345
		if(name == null || name.length() == 0){
346
			return "";
347
		} else {
348
			String result = name.charAt(0) + "";
349
			boolean previousWasSpace = false;;
350
			for(int i = 1; i < name.length(); i++){
351
				char curLetter = name.charAt(i);
352
				if(curLetter == '_'){
353
					result += " ";
354
					previousWasSpace = true;
355
				} else {
356
					if(previousWasSpace){
357
						result += Character.toUpperCase(curLetter);
358
					} else {
359
						result += Character.toLowerCase(curLetter);
360
					}
361
					previousWasSpace = false;
362
				}
363
			}
364
			return result;
365
		}
366
	}
367
	
321 368
	private class AddLoadBalancerTask extends AsyncTask<Void, Void, HttpBundle> {
322 369
		private CloudServersException exception;
323 370

  
......
361 408
		}
362 409
	}
363 410

  
411
	private void printNodes(ArrayList<Node> nodes){
412
		for(Node n : nodes){
413
			Log.d("info", "node is: " + n.getAddress());
414
		}
415
	}
416
	
364 417
	@SuppressWarnings("unchecked")
365 418
	@Override
366 419
	protected void onActivityResult (int requestCode, int resultCode, Intent data){
......
368 421
			//set node list
369 422
			nodes = ((ArrayList<Node>)data.getSerializableExtra("nodes"));
370 423
			updateNodesIndicatorLight();
424
			printNodes(nodes);
371 425
		}
372 426
		else if(requestCode == ADD_NODES_ACTIVITY_CODE && resultCode == RESULT_CANCELED){
373 427
			//don't change list
b/src/com/rackspacecloud/android/AddMoreNodesActivity.java
34 34

  
35 35
	private static final int ADD_NODE_CODE = 178;
36 36
	private static final int ADD_EXTERNAL_NODE_CODE = 188;
37
	private ArrayList<Server> servers; 
37
	private ArrayList<Server> possibleNodes; 
38
	//the last position in the listview that was clicked
38 39
	private int lastCheckedPos;
40
	//the location in nodes of the last node that was clicked
41
	private int positionOfNode;
39 42
	private ArrayList<Node> nodes;
40 43
	private ArrayList<Node> nodesToAdd;
41 44
	private LoadBalancer loadBalancer;
......
57 60
		outState.putSerializable("nodes", nodes);
58 61
		outState.putSerializable("loadBalancer", loadBalancer);
59 62
		outState.putSerializable("nodesToAdd", nodesToAdd);
60
		outState.putSerializable("servers", servers);
63
		outState.putSerializable("possibleNodes", possibleNodes);
64
		outState.putInt("lastCheckedPos", lastCheckedPos);
65
		outState.putInt("positionOfNode", positionOfNode);
61 66
	}
62 67

  
63 68
	@SuppressWarnings("unchecked")
......
78 83
			}
79 84
		}
80 85

  
86
		if (state != null && state.containsKey("lastCheckedPos")){
87
			lastCheckedPos = (Integer) state.getSerializable("lastCheckedPos");
88
		}
89

  
90
		if (state != null && state.containsKey("positionOfNode")){
91
			positionOfNode = (Integer) state.getSerializable("positionOfNode");
92
		}
93

  
81 94
		if (state != null && state.containsKey("nodesToAdd")){
82 95
			nodesToAdd = (ArrayList<Node>) state.getSerializable("nodesToAdd");
83 96
		}
......
85 98
			nodesToAdd = new ArrayList<Node>();
86 99
		}
87 100

  
88
		if (state != null && state.containsKey("servers") && state.getSerializable("servers") != null) {
89
			servers = (ArrayList<Server>) state.getSerializable("servers");
90
			if (servers.size() == 0) {
101
		if (state != null && state.containsKey("possibleNodes") && state.getSerializable("possibleNodes") != null) {
102
			possibleNodes = (ArrayList<Server>) state.getSerializable("servers");
103
			if (possibleNodes.size() == 0) {
91 104
				displayNoServersCell();
92 105
			} else {
93 106
				getListView().setDividerHeight(1); // restore divider lines
......
115 128

  
116 129
			@Override
117 130
			public void onClick(View v) {
131
				positionOfNode = -1;
118 132
				Intent viewIntent = new Intent(getContext(), AddExternalNodeActivity.class);
119
				viewIntent.putExtra("weighted", false);
133
				viewIntent.putExtra("weighted", loadBalancer.getAlgorithm().toLowerCase().contains("weighted"));
120 134
				startActivityForResult(viewIntent, ADD_EXTERNAL_NODE_CODE);
121 135
			}
122 136
		});
......
131 145
	//When a list item is click just change the checkbox state
132 146
	//and then the checkbox's onClick will be performed
133 147
	protected void onListItemClick(ListView l, View v, int position, long id) {
134
		if (servers != null && servers.size() > 0) {
135
			LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
136
			ListView serversList = (ListView) linear.findViewById(android.R.id.list);
137
			View row = serversList.getChildAt(position);
138
			CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
139
			if(!checkBox.isChecked()){
140
				//if the checkbox was not previously checked, treat the listItemClick
141
				//the same as checking the checkbox
142
				checkBox.setChecked(!checkBox.isChecked());
143
			} else {
144
				//if the checkbox was already checked when the listItemClick occurred,
145
				//then treat it like an edit
148
		if (possibleNodes != null && possibleNodes.size() > 0) {
149
			if(!possibleNodes.get(position).getName().equals("External Node")){
150
				LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
151
				ListView serversList = (ListView) linear.findViewById(android.R.id.list);
152
				View row = serversList.getChildAt(position);
153
				CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
154
				if(!checkBox.isChecked()){
155
					//if the checkbox was not previously checked, treat the listItemClick
156
					//the same as checking the checkbox
157
					checkBox.setChecked(!checkBox.isChecked());
158
				} else {
159
					//if the checkbox was already checked when the listItemClick occurred,
160
					//then treat it like an edit
146 161

  
147
				Server server = servers.get(position);
162
					Server server = possibleNodes.get(position);
148 163

  
149
				//Need to put all the ip's of the server into one
150
				//list so they can all be displayed in one spinner
151
				String[] ipAddresses = getAllIpsOfServer(server);
164
					//Need to put all the ip's of the server into one
165
					//list so they can all be displayed in one spinner
166
					String[] ipAddresses = getAllIpsOfServer(server);
152 167

  
153
				Node node = getNodeFromServer(server);
168
					Node node = getNodeFromServer(server);
154 169

  
170
					positionOfNode = findNodePosition(node);
171
					lastCheckedPos = position;
172

  
173
					Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
174
					viewIntent.putExtra("ipAddresses", ipAddresses);
175
					viewIntent.putExtra("name", server.getName());
176
					if(node != null){
177
						viewIntent.putExtra("node", node);
178
					}
179
					viewIntent.putExtra("weighted", loadBalancer.getAlgorithm().toLowerCase().contains("weighted"));
180
					startActivityForResult(viewIntent, ADD_NODE_CODE);
181
				}
182
			} else {
183
				//When clicked on an external node
184
				Server server = possibleNodes.get(position);
185
				Node node = getNodeFromServer(server);
186
				positionOfNode = findNodePosition(node);
155 187
				lastCheckedPos = position;
156
				Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
157
				viewIntent.putExtra("ipAddresses", ipAddresses);
158
				viewIntent.putExtra("name", server.getName());
188
				Intent viewIntent = new Intent(getContext(), AddExternalNodeActivity.class);
159 189
				if(node != null){
160 190
					viewIntent.putExtra("node", node);
161 191
				}
162 192
				//weighted is false, because on initial node add
163 193
				//weight is not option
164 194
				viewIntent.putExtra("weighted", false);
165
				startActivityForResult(viewIntent, ADD_NODE_CODE);
195
				startActivityForResult(viewIntent, ADD_EXTERNAL_NODE_CODE);
166 196
			}
197
		}
198
	}
167 199

  
200
	//return the location of node in nodes
201
	//if it is no in there then -1
202
	private int findNodePosition(Node node){
203
		for(int i = 0; i < nodesToAdd.size(); i++){
204
			String address = node.getAddress();
205
			if(address.equals(nodesToAdd.get(i).getAddress())){
206
				return i;
207
			}
168 208
		}
209
		return -1;
169 210
	}
170 211

  
171 212
	private void displayNoServersCell() {
......
194 235
		}
195 236

  
196 237
		String[] serverNames = new String[servers.size()];
197
		this.servers = new ArrayList<Server>();
238
		this.possibleNodes = new ArrayList<Server>();
198 239

  
199 240
		for(int i = 0; i < servers.size(); i++){
200 241
			serverNames[i] = servers.get(i).getName();
201
			this.servers.add(i, servers.get(i));
242
			this.possibleNodes.add(i, servers.get(i));
202 243
		}
203 244

  
204 245
		if (serverNames.length == 0) {
......
247 288
	// * Adapter/
248 289
	class ServerAdapter extends ArrayAdapter<Server> {
249 290
		ServerAdapter() {
250
			super(AddMoreNodesActivity.this, R.layout.listservernodecell, servers);
291
			super(AddMoreNodesActivity.this, R.layout.listservernodecell, possibleNodes);
251 292
		}
252 293

  
253 294
		public View getView(int position, View convertView, ViewGroup parent) {
254 295

  
255
			final Server server = servers.get(position);
296
			final Server server = possibleNodes.get(position);
256 297
			LayoutInflater inflater = getLayoutInflater();
257 298
			View row = inflater.inflate(R.layout.listservernodecell, parent, false);
258 299

  
......
302 343
				@Override
303 344
				public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
304 345
					if(isChecked){
346
						//if node is being check it won't be in nodes positionOfNode is -1
347
						positionOfNode = -1;
305 348
						lastCheckedPos = pos;
306 349
						Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
307 350
						viewIntent.putExtra("ipAddresses", ipAddresses);
......
312 355
					else{
313 356
						removeNodeFromList(server);
314 357
						if(server.getName().equals("External Node")){
315
							servers.remove(server);
316
							setServerList(servers);
358
							possibleNodes.remove(server);
359
							setServerList(possibleNodes);
317 360
						}
318 361
					}
319 362
				}
......
338 381
	}
339 382
	private boolean serverHasIp(Server server, String address){
340 383
		String[] addresses = server.getPrivateIpAddresses();
341
		for(int i = 0; i < addresses.length; i++){
342
			Log.d("info", "server address: " + addresses[i] + " node address: " + address);
343
			if(addresses[i].equals(address)){
344
				return true;
384
		if(addresses != null){
385
			for(int i = 0; i < addresses.length; i++){
386
				if(addresses[i].equals(address)){
387
					return true;
388
				}
345 389
			}
346 390
		}
347 391
		addresses = server.getPublicIpAddresses();
348
		for(int i = 0; i < addresses.length; i++){
349
			if(addresses[i].equals(address)){
350
				return true;
392
		if(addresses != null){
393
			for(int i = 0; i < addresses.length; i++){
394
				if(addresses[i].equals(address)){
395
					return true;
396
				}
351 397
			}
352 398
		}
353 399
		return false;
......
436 482
	}
437 483

  
438 484
	private String getNameFromIp(String address){
439
		for(Server s: servers){
485
		for(Server s: possibleNodes){
440 486
			if(serverHasIp(s, address)){
441 487
				return s.getName();
442 488
			}
......
445 491
	}
446 492

  
447 493
	private boolean isCloudServerIp(String address){
448
		for(Server s : servers){
494
		for(Server s : possibleNodes){
449 495
			if(serverHasIp(s, address)){
450 496
				return true;
451 497
			}
......
487 533
	protected void onActivityResult(int requestCode, int resultCode, Intent data){
488 534
		int pos = lastCheckedPos;
489 535
		if(requestCode == ADD_NODE_CODE && resultCode == RESULT_OK){
490
			//data will be null is user back out on edit
536
			//data will be null if user backed out on edit
491 537
			//we dont need to do anything then
492 538
			//if new node added data won't be null
493 539
			//so create the new node and add it to the list
494 540
			if(data != null){
541
				//will remove the node if it's already in the list 
542
				//so we can update it
543
				if(positionOfNode >= 0){
544
					nodesToAdd.remove(positionOfNode);
545
				}
546

  
495 547
				Node node = new Node();
496 548
				node.setAddress(data.getStringExtra("nodeIp"));
497 549
				node.setCondition(data.getStringExtra("nodeCondition"));
498
				node.setName(servers.get(pos).getName());
550
				node.setName(possibleNodes.get(pos).getName());
499 551
				node.setPort(data.getStringExtra("nodePort"));
500 552
				node.setWeight(data.getStringExtra("nodeWeight"));
501 553
				nodesToAdd.add(node);
......
522 574
			 * so they can select it from there
523 575
			 */	
524 576
			if(!isCloudServerIp(node.getAddress())){
577

  
578
				if(positionOfNode >= 0){
579
					nodesToAdd.remove(positionOfNode);
580
				}
581

  
525 582
				nodesToAdd.add(node);
526 583
				//Add it to server list so it display in the listview
527 584
				Server server = new Server();
528 585
				server.setName("External Node");
529 586
				String[] ip = {data.getStringExtra("nodeIp")};
530 587
				server.setPrivateIpAddresses(ip);
531
				servers.add(server);
532
				setServerList(servers);
588
				possibleNodes.add(server);
589
				setServerList(possibleNodes);
533 590
			} else {
534 591
				showAlert("Error", "This IP belongs to a cloud server: \"" + getNameFromIp(node.getAddress()) 
535 592
						+ "\", please select it from the list.");
536 593
			}
537 594
		}
595
		printTheNodes();
596
	}
597

  
598
	private void printTheNodes(){
599
		for(Node n: nodesToAdd){
600
			Log.d("info", "address: " + n.getAddress() + " Port: " + n.getPort() + " Cond: " + n.getCondition());
601
		}
602
		Log.d("info", " SPACE ");
538 603
	}
539 604
}
b/src/com/rackspacecloud/android/AddNodeActivity.java
4 4

  
5 5
import android.content.Intent;
6 6
import android.os.Bundle;
7
import android.util.Log;
8 7
import android.view.View;
9 8
import android.view.View.OnClickListener;
10 9
import android.view.Window;
......
24 23
	private String selectedPort;
25 24
	private String selectedIp;
26 25
	private String selectedWeight;
27
	private boolean weighted;
28 26
	private String selectedCondition;
27
	private boolean weighted;
29 28
	private Spinner conditionSpinner;
30 29
	private Spinner ipAddressSpinner;
31 30
	private EditText weightText;
......
44 43

  
45 44
	protected void restoreState(Bundle state) {
46 45
		super.restoreState(state);
46
		
47
		if (state != null){
48
			if(state.containsKey("selectedPort")){
49
				selectedPort = (String) state.getString("selectedPort");
50
			}
51
			
52
			if(state.containsKey("selectedIp")){
53
				selectedIp = (String) state.getString("selectedIp");
54
			}
55
			
56
			if(state.containsKey("selectedWeight")){
57
				selectedWeight = (String) state.getString("selectedWeight");
58
			}
59
		
60
			if(state.containsKey("selectedCondition")){
61
				selectedCondition = (String) state.getString("selectedCondition");
62
			}
63
		}
64
		
47 65
		setupInputs();
48 66
	}
67
	
68
	@Override
69
	protected void onSaveInstanceState(Bundle outState) {
70
		super.onSaveInstanceState(outState);
71
		outState.putString("selectedPort", selectedPort);
72
		outState.putString("selectedIp", selectedIp);
73
		outState.putString("selectedWeight", selectedWeight);
74
		outState.putString("selectedCondition", selectedCondition);
75
	}
49 76

  
50 77
	private void setupInputs(){
51 78
		setupWeightedText();
......
71 98

  
72 99
	private void loadConditionSpinner(){
73 100
		conditionSpinner = (Spinner) findViewById(R.id.node_condition_spinner);
74
	
75 101
		ArrayAdapter<String> conditionAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, CONDITIONS);
76 102
		conditionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
77 103
		conditionSpinner.setAdapter(conditionAdapter);
78
	
104

  
79 105
		conditionSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
80
	
106

  
81 107
			@Override
82 108
			public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
83 109
				selectedCondition = CONDITIONS[pos];	
84 110
			}
85
	
111

  
86 112
			@Override
87 113
			public void onNothingSelected(AdapterView<?> arg0) {
88
	
114

  
89 115
			}
90
	
116

  
91 117
		});
92 118
	}
93 119

  
......
96 122
		ArrayAdapter<String> ipAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, ipAddresses);
97 123
		ipAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
98 124
		ipAddressSpinner.setAdapter(ipAdapter);
99
	
125

  
100 126
		ipAddressSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
101
	
127

  
102 128
			@Override
103 129
			public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
104 130
				selectedIp = ipAddresses[pos];	
105 131
			}
106
	
132

  
107 133
			@Override
108 134
			public void onNothingSelected(AdapterView<?> arg0) {
109
	
135

  
110 136
			}
111
	
137

  
112 138
		});
113
	
139

  
114 140
	}
115 141

  
116 142
	private void setUpButton(){
......
132 158
					data.putExtra("nodeIp", selectedIp);
133 159
					data.putExtra("nodePort", selectedPort);
134 160
					data.putExtra("nodeCondition", selectedCondition);
135
					Log.d("info", "saving the weight as " + selectedWeight);
136 161
					data.putExtra("nodeWeight", selectedWeight);
137 162
					setResult(RESULT_OK, data);
138 163
					finish();
139 164
				}
140

  
141 165
			}
142 166
		});
143 167
	}
......
162 186
	//returns the location in objects of object
163 187
	//if it doesn't exist return -1
164 188
	private int getLocation(Object[] objects, Object object){
165
		for(int i = 0; i < objects.length; i++){
166
			if(objects[i].equals(object)){
167
				return i;
189
		if(objects == null || object == null){
190
			return -1;
191
		} else {
192
			for(int i = 0; i < objects.length; i++){
193
				if(objects[i].toString().equalsIgnoreCase(object.toString())){
194
					return i;
195
				}
168 196
			}
197
			return -1;
169 198
		}
170
		return -1;
171 199
	}
172 200

  
173 201
	private boolean validPort(){
174
		return !selectedPort.equals("") && Integer.valueOf(selectedPort) > 0 && Integer.valueOf(selectedPort) < 65536;
202
		boolean result;
203
		try{
204
			result = !selectedPort.equals("") && Integer.valueOf(selectedPort) > 0 && Integer.valueOf(selectedPort) < 65536;
205
		} catch (NumberFormatException e) {
206
			result = false;
207
		}
208
		return result;
175 209
	}
176

  
177 210
	private Boolean validWeight(String weight){
178 211
		if(weight.equals("")){
179 212
			return false;
b/src/com/rackspacecloud/android/AddNodesActivity.java
30 30
	private static final int ADD_EXTERNAL_NODE_CODE = 188;
31 31

  
32 32
	//servers are what are displayed in the ListView
33
	private ArrayList<Server> servers;
33
	//(possible and checked nodes)
34
	private ArrayList<Server> possibleNodes;
34 35
	//nodes are the nodes the user has selected
35 36
	private ArrayList<Node> nodes;
37
	//the last position in the listview that was clicked
36 38
	private int lastCheckedPos;
39
	//the location in nodes of the last node that was clicked
40
	private int positionOfNode;
37 41

  
38 42
	@SuppressWarnings("unchecked")
39 43
	@Override
40 44
	public void onCreate(Bundle savedInstanceState) {
41 45
		super.onCreate(savedInstanceState);
42 46
		nodes = (ArrayList<Node>) this.getIntent().getExtras().get("nodes");
47
		possibleNodes = (ArrayList<Server>) this.getIntent().getExtras().get("possibleNodes");
43 48
		setContentView(R.layout.addnodes);
44 49
		restoreState(savedInstanceState);
45 50
	}
......
48 53
	protected void onSaveInstanceState(Bundle outState) {
49 54
		super.onSaveInstanceState(outState);
50 55
		outState.putSerializable("nodes", nodes);
51
		outState.putSerializable("servers", servers);
56
		outState.putSerializable("possibleNodes", possibleNodes);
57
		outState.putInt("lastCheckedPos", lastCheckedPos);
58
		outState.putInt("positionOfNode", positionOfNode);
52 59
	}
53 60

  
54 61
	@SuppressWarnings("unchecked")
......
61 68
				nodes = new ArrayList<Node>();
62 69
			}
63 70
		}
71
		
72
		if (state != null && state.containsKey("lastCheckedPos")){
73
			lastCheckedPos = (Integer) state.getSerializable("lastCheckedPos");
74
		}
75
		
76
		if (state != null && state.containsKey("positionOfNode")){
77
			positionOfNode = (Integer) state.getSerializable("positionOfNode");
78
		}
64 79

  
65
		if (state != null && state.containsKey("servers")) {
66
			servers = (ArrayList<Server>) state.getSerializable("servers");
67
			if (servers.size() == 0) {
80
		if (state != null && state.containsKey("possibleNodes")) {
81
			possibleNodes = (ArrayList<Server>) state.getSerializable("possibleNodes");
82
			if (possibleNodes.size() == 0) {
68 83
				displayNoServersCell();
69 84
			} else {
70 85
				getListView().setDividerHeight(1); // restore divider lines
......
81 96
			public void onClick(View v) {
82 97
				Intent viewIntent = new Intent();
83 98
				viewIntent.putExtra("nodes", nodes);
99
				viewIntent.putExtra("possibleNodes", possibleNodes);
84 100
				setResult(RESULT_OK, viewIntent);
101
				printTheNodes();
85 102
				finish();
86 103
			}
87 104
		});
......
91 108

  
92 109
			@Override
93 110
			public void onClick(View v) {
111
				positionOfNode = -1;
94 112
				Intent viewIntent = new Intent(getContext(), AddExternalNodeActivity.class);
95 113
				//when first creating a load balancer
96 114
				//weighting nodes in not an option
......
107 125
	}
108 126

  
109 127
	protected void onListItemClick(ListView l, View v, int position, long id) {
110
		if (servers != null && servers.size() > 0) {
111
			LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
112
			ListView serversList = (ListView) linear.findViewById(android.R.id.list);
113
			View row = serversList.getChildAt(position);
114
			CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
115
			if(!checkBox.isChecked()){
116
				//if the checkbox was not previously checked, treat the listItemClick
117
				//the same as checking the checkbox
118
				checkBox.setChecked(!checkBox.isChecked());
119
			} else {
120
				//if the checkbox was already checked when the listItemClick occurred,
121
				//then treat it like an edit
122

  
123
				Server server = servers.get(position);
124

  
125
				//Need to put all the ip's of the server into one
126
				//list so they can all be displayed in one spinner
127
				String[] ipAddresses = getAllIpsOfServer(server);
128

  
129
				Node node = getNodeFromServer(server);
130

  
131
				lastCheckedPos = position;
132
				Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
133
				viewIntent.putExtra("ipAddresses", ipAddresses);
134
				viewIntent.putExtra("name", server.getName());
135
				if(node != null){
136
					viewIntent.putExtra("node", node);
128
		if (possibleNodes != null && possibleNodes.size() > 0) {
129
			if(!possibleNodes.get(position).getName().equals("External Node")){
130
				LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
131
				ListView serversList = (ListView) linear.findViewById(android.R.id.list);
132
				View row = serversList.getChildAt(position);
133
				CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
134
				if(!checkBox.isChecked()){
135
					//if the checkbox was not previously checked, treat the listItemClick
136
					//the same as checking the checkbox
137
					checkBox.setChecked(!checkBox.isChecked());
138
				} else {
139
					//if the checkbox was already checked when the listItemClick occurred,
140
					//then treat it like an edit
141

  
142
					Server server = possibleNodes.get(position);
143

  
144
					//Need to put all the ip's of the server into one
145
					//list so they can all be displayed in one spinner
146
					String[] ipAddresses = getAllIpsOfServer(server);
147

  
148
					Node node = getNodeFromServer(server);
149
					
150
					positionOfNode = findNodePosition(node);
151
					lastCheckedPos = position;
152
					
153
					Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
154
					viewIntent.putExtra("ipAddresses", ipAddresses);
155
					viewIntent.putExtra("name", server.getName());
156
					if(node != null){
157
						viewIntent.putExtra("node", node);
158
					}
159
					//weighted is false, because on initial node add
160
					//weight is not option
161
					viewIntent.putExtra("weighted", false);
162
					startActivityForResult(viewIntent, ADD_NODE_CODE);
137 163
				}
138
				//weighted is false, because on initial node add
139
				//weight is not option
140
				viewIntent.putExtra("weighted", false);
141
				startActivityForResult(viewIntent, ADD_NODE_CODE);
164
			} else {
165
			//When clicked on an external node
166
			Server server = possibleNodes.get(position);
167
			Node node = getNodeFromServer(server);
168
			positionOfNode = findNodePosition(node);
169
			lastCheckedPos = position;
170
			Intent viewIntent = new Intent(getContext(), AddExternalNodeActivity.class);
171
			if(node != null){
172
				viewIntent.putExtra("node", node);
173
			}
174
			//weighted is false, because on initial node add
175
			//weight is not option
176
			viewIntent.putExtra("weighted", false);
177
			startActivityForResult(viewIntent, ADD_EXTERNAL_NODE_CODE);
142 178
			}
143

  
144 179
		}
145 180
	}
181
	
182
	//return the location of node in nodes
183
	//if it is no in there then -1
184
	private int findNodePosition(Node node){
185
		for(int i = 0; i < nodes.size(); i++){
186
			String address = node.getAddress();
187
			if(address.equals(nodes.get(i).getAddress())){
188
				return i;
189
			}
190
		}
191
		return -1;
192
	}
146 193

  
147 194
	private void displayNoServersCell() {
148 195
		String a[] = new String[1];
......
158 205
			servers = new ArrayList<Server>();
159 206
		}
160 207
		String[] serverNames = new String[servers.size()];
161
		this.servers = new ArrayList<Server>();
208
		this.possibleNodes = new ArrayList<Server>();
162 209

  
163 210
		if (servers != null) {
164 211
			for (int i = 0; i < servers.size(); i++) {
165 212
				Server server = servers.get(i);
166
				this.servers.add(i, server);
213
				this.possibleNodes.add(i, server);
167 214
				serverNames[i] = server.getName();
168 215
			}
169 216
		}
......
183 230
	// * Adapter/
184 231
	class ServerAdapter extends ArrayAdapter<Server> {
185 232
		ServerAdapter() {
186
			super(AddNodesActivity.this, R.layout.listservernodecell, servers);
233
			super(AddNodesActivity.this, R.layout.listservernodecell, possibleNodes);
187 234
		}
188 235

  
189 236
		public View getView(int position, View convertView, ViewGroup parent) {
190 237

  
191
			final Server server = servers.get(position);
238
			final Server server = possibleNodes.get(position);
192 239
			LayoutInflater inflater = getLayoutInflater();
193 240
			View row = inflater.inflate(R.layout.listservernodecell, parent, false);
194 241

  
......
202 249
				sublabel.setText(server.getFlavor().getName() + " - " + server.getImage().getName());
203 250
			}
204 251

  
205

  
206 252
			//Need to put all the ip's of the server into one
207 253
			//list so they can all be displayed in one spinner
208 254
			final String[] ipAddresses = getAllIpsOfServer(server);
......
219 265
				@Override
220 266
				public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
221 267
					if(isChecked){
268
						//if node is being check it won't be in nodes positionOfNode is -1
269
						positionOfNode = -1;
222 270
						lastCheckedPos = pos;
223 271
						Intent viewIntent = new Intent(getContext(), AddNodeActivity.class);
224 272
						viewIntent.putExtra("ipAddresses", ipAddresses);
......
231 279
					else{
232 280
						removeNodeFromList(server);
233 281
						if(server.getName().equals("External Node")){
234
							servers.remove(server);
235
							setServerList(servers);
282
							possibleNodes.remove(server);
283
							setServerList(possibleNodes);
236 284
						}
237 285
					}
238 286
				}
......
269 317
	}
270 318

  
271 319
	private String getNameFromIp(String address){
272
		for(Server s: servers){
320
		for(Server s: possibleNodes){
273 321
			if(serverHasIp(s, address)){
274 322
				return s.getName();
275 323
			}
......
280 328
	//returns true if address is an address of
281 329
	//one of the users cloud servers
282 330
	private boolean isCloudServerIp(String address){
283
		for(Server s : servers){
331
		for(Server s : possibleNodes){
284 332
			if(serverHasIp(s, address)){
285 333
				return true;
286 334
			}
......
380 428
		}
381 429
	}
382 430

  
383
	protected void onActivityResult(int requestCode, int resultCode, Intent data){
431
	//removes a node with ip of address from nodes
432
	//if one doesnt exists doesn nothing
433
	/*private void removeNodeWithIp(String address){
434
		for(int i = 0; i < nodes.size(); i++){
435
			Node n = nodes.get(i);
436
			if(n.getAddress().equals(address)){
437
				nodes.remove(i);
438
				break;
439
			}
440
		}
441
	}*/
442

  
443
	protected void onActivityResult(int requestCode, int resultCode, Intent data){	
384 444
		int pos = lastCheckedPos;
385 445
		if(requestCode == ADD_NODE_CODE && resultCode == RESULT_OK){
386 446
			//data will be null is user back out on edit
......
388 448
			//if new node added data won't be null
389 449
			//so create the new node and add it to the list
390 450
			if(data != null){
451
				//will remove the node if it's already in the list 
452
				//so we can update it
453
				//removeNodeWithIp(data.getStringExtra("nodeIp"));
454
				if(positionOfNode >= 0){
455
					nodes.remove(positionOfNode);
456
				}
457
				
391 458
				Node node = new Node();
392 459
				node.setAddress(data.getStringExtra("nodeIp"));
393 460
				node.setCondition(data.getStringExtra("nodeCondition"));
394
				node.setName(servers.get(pos).getName());
461
				node.setName(possibleNodes.get(pos).getName());
395 462
				node.setPort(data.getStringExtra("nodePort"));
396 463
				node.setWeight(data.getStringExtra("nodeWeight"));
397 464
				nodes.add(node);
......
401 468
			//uncheck the node at lastCheckedPos
402 469
			LinearLayout linear = (LinearLayout) findViewById(R.id.nodes_linear_layout); 
403 470
			ListView serversList = (ListView) linear.findViewById(android.R.id.list);
471
			Log.d("info", "number of items in serverList " + serversList.getChildCount());
472
			Log.d("info", "lastCheckedPos is " + Integer.toString(pos));
404 473
			View row = serversList.getChildAt(pos);
474
			Log.d("info", ("is row null? " + Boolean.toString(row == null)));
405 475
			CheckBox checkBox = (CheckBox)row.findViewById(R.id.add_node_checkbox);
406 476
			checkBox.setChecked(false);
407 477
		}
......
419 489
			 * so they can select it from there
420 490
			 */	
421 491
			if(!isCloudServerIp(node.getAddress())){
492
				
493
				if(positionOfNode >= 0){
494
					nodes.remove(positionOfNode);
495
				}
496
				
422 497
				nodes.add(node);
423 498
				//Add it to server list so it display in the listview
424 499
				Server server = new Server();
425 500
				server.setName("External Node");
426 501
				String[] ip = {data.getStringExtra("nodeIp")};
427 502
				server.setPrivateIpAddresses(ip);
428
				servers.add(server);
429
				setServerList(servers);
503
				possibleNodes.add(server);
504
				setServerList(possibleNodes);
430 505
			} else {
431 506
				showAlert("Error", "This IP belongs to a cloud server: \"" + getNameFromIp(node.getAddress()) 
432 507
						+ "\", please select it from the list.");
433 508
			}
434 509
		}
435
		Log.d("info", "number of nodes is " + nodes.size());
510
		printTheNodes();
436 511
	}
437 512

  
513
	private void printTheNodes(){
514
		for(Node n: nodes){
515
			Log.d("info", "address: " + n.getAddress() + " Port: " + n.getPort() + " Cond: " + n.getCondition());
516
		}
517
		Log.d("info", " SPACE ");
518
	}
438 519

  
439 520
}
b/src/com/rackspacecloud/android/EditLoadBalancerActivity.java
165 165

  
166 166
		for(int i = 0; i < Algorithm.getAlgorithms().size(); i++){
167 167
			algorithms[i] = Algorithm.getAlgorithms().get(i);
168
			algorithmNames[i] = Algorithm.getAlgorithms().get(i).getName();
169
			if(algorithmNames[i].equals(selectedAlgorithm)){
168
			algorithmNames[i] = getPrettyAlgoName(Algorithm.getAlgorithms().get(i).getName());
169
			if(algorithmNames[i].equals(getPrettyAlgoName(selectedAlgorithm))){
170 170
				defaultPosition = i;
171 171
			}
172 172
		}
......
176 176
		algorithmSpinner.setAdapter(algorithmAdapter);
177 177
		algorithmSpinner.setSelection(defaultPosition);
178 178
	}
179
	
180
	private String getPrettyAlgoName(String name){
181
		if(name == null || name.length() == 0){
182
			return "";
183
		} else {
184
			String result = name.charAt(0) + "";
185
			boolean previousWasSpace = false;;
186
			for(int i = 1; i < name.length(); i++){
187
				char curLetter = name.charAt(i);
188
				if(curLetter == '_'){
189
					result += " ";
190
					previousWasSpace = true;
191
				} else {
192
					if(previousWasSpace){
193
						result += Character.toUpperCase(curLetter);
194
					} else {
195
						result += Character.toLowerCase(curLetter);
196
					}
197
					previousWasSpace = false;
198
				}
199
			}
200
			return result;
201
		}
202
	}
179 203

  
180 204
	public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
181 205
		if (parent == protocolSpinner) {
b/src/com/rackspacecloud/android/ViewLoadBalancerActivity.java
308 308
			port.setText(loadBalancer.getPort());
309 309

  
310 310
			TextView algorithm = (TextView) findViewById(R.id.view_algorithm);
311
			algorithm.setText(loadBalancer.getAlgorithm());
311
			algorithm.setText(getPrettyAlgoName(loadBalancer.getAlgorithm()));
312 312

  
313 313
			TextView status = (TextView) findViewById(R.id.view_status);
314 314
			if (!"ACTIVE".equals(loadBalancer.getStatus())) {
......
332 332
			loadVirutalIpData();
333 333
		}
334 334
	}
335
	
336
	private String getPrettyAlgoName(String name){
337
		if(name == null || name.length() == 0){
338
			return "";
339
		} else {
340
			String result = name.charAt(0) + "";
341
			boolean previousWasSpace = false;;
342
			for(int i = 1; i < name.length(); i++){
343
				char curLetter = name.charAt(i);
344
				if(curLetter == '_'){
345
					result += " ";
346
					previousWasSpace = true;
347
				} else {
348
					if(previousWasSpace){
349
						result += Character.toUpperCase(curLetter);
350
					} else {
351
						result += Character.toLowerCase(curLetter);
352
					}
353
					previousWasSpace = false;
354
				}
355
			}
356
			return result;
357
		}
358
	}
335 359

  
336 360
	private void loadVirutalIpData() {
337 361
		int layoutIndex = 0;

Also available in: Unified diff