SEBSERV-63 client connection table sort

This commit is contained in:
anhefti 2019-07-18 16:22:19 +02:00
parent 60a997d6f6
commit 043f6b72e5
4 changed files with 266 additions and 148 deletions

View file

@ -152,6 +152,30 @@ public final class ClientConnection implements GrantEntity {
return true;
}
public boolean dataEquals(final ClientConnection other) {
if (other == null) {
return true;
}
if (this.clientAddress == null) {
if (other.clientAddress != null)
return false;
} else if (!this.clientAddress.equals(other.clientAddress))
return false;
if (this.status != other.status)
return false;
if (this.userSessionId == null) {
if (other.userSessionId != null)
return false;
} else if (!this.userSessionId.equals(other.userSessionId))
return false;
if (this.virtualClientAddress == null) {
if (other.virtualClientAddress != null)
return false;
} else if (!this.virtualClientAddress.equals(other.virtualClientAddress))
return false;
return true;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();

View file

@ -9,18 +9,21 @@
package ch.ethz.seb.sebserver.gbl.model.session;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.util.Utils;
public class ClientConnectionData {
@JsonProperty("clientConnection")
public final ClientConnection clientConnection;
@JsonProperty("indicatorValues")
public final Collection<? extends IndicatorValue> indicatorValues;
public final List<? extends IndicatorValue> indicatorValues;
@JsonCreator
protected ClientConnectionData(
@ -28,7 +31,7 @@ public class ClientConnectionData {
@JsonProperty("indicatorValues") final Collection<? extends SimpleIndicatorValue> indicatorValues) {
this.clientConnection = clientConnection;
this.indicatorValues = indicatorValues;
this.indicatorValues = Utils.immutableListOf(indicatorValues);
}
protected ClientConnectionData(
@ -36,7 +39,7 @@ public class ClientConnectionData {
@JsonProperty("indicatorValues") final List<? extends IndicatorValue> indicatorValues) {
this.clientConnection = clientConnection;
this.indicatorValues = indicatorValues;
this.indicatorValues = Utils.immutableListOf(indicatorValues);
}
@JsonIgnore
@ -52,6 +55,28 @@ public class ClientConnectionData {
return this.indicatorValues;
}
public boolean dataEquals(final ClientConnectionData other) {
if (!this.clientConnection.dataEquals(other.clientConnection)) {
return false;
}
if (this.indicatorValues.size() != other.indicatorValues.size()) {
return false;
}
final Iterator<? extends IndicatorValue> i1 = this.indicatorValues.iterator();
final Iterator<? extends IndicatorValue> i2 = other.indicatorValues.iterator();
while (i1.hasNext()) {
final IndicatorValue iv1 = i1.next();
final IndicatorValue iv2 = i2.next();
if (iv1.getType() != iv2.getType() || iv1.getValue() != iv2.getValue()) {
return false;
}
}
return true;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();

View file

@ -11,9 +11,12 @@ package ch.ethz.seb.sebserver.gui.service.session;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
@ -41,6 +44,8 @@ public final class ClientConnectionTable {
private static final int BOTTOM_PADDING = 20;
private final static String STATUS_LOC_TEXT_KEY_PREFIX = "sebserver.monitoring.connection.status.";
private final static LocTextKey CONNECTION_ID_TEXT_KEY =
new LocTextKey("sebserver.monitoring.connection.list.column.id");
private final static LocTextKey CONNECTION_ADDRESS_TEXT_KEY =
@ -56,9 +61,10 @@ public final class ClientConnectionTable {
private final Color color1;
private final Color color2;
private final Color color3;
private int tableWidth;
private final Map<Long, UpdatableTableItem> tableMapping;
private int tableWidth;
private boolean needsSort = false;
private LinkedHashMap<Long, UpdatableTableItem> tableMapping;
public ClientConnectionTable(
final WidgetFactory widgetFactory,
@ -105,7 +111,7 @@ public final class ClientConnectionTable {
this.color2 = new Color(display, new RGB(249, 166, 2), 100);
this.color3 = new Color(display, new RGB(255, 0, 0), 100);
this.tableMapping = new HashMap<>();
this.tableMapping = new LinkedHashMap<>();
this.table.layout();
}
@ -121,47 +127,28 @@ public final class ClientConnectionTable {
for (final ClientConnectionData data : connectionInfo) {
final UpdatableTableItem tableItem = this.tableMapping.computeIfAbsent(
data.getConnectionId(),
userIdentifier -> new UpdatableTableItem(this.table, data.getConnectionId()));
userIdentifier -> new UpdatableTableItem(data.getConnectionId()));
tableItem.push(data);
}
}
public void updateGUI() {
boolean sort = false;
for (final UpdatableTableItem uti : this.tableMapping.values()) {
if (uti.tableItem == null) {
createTableItem(uti);
updateIndicatorValues(uti, false);
updateConnectionStatusColor(uti);
sort = true;
} else {
if (uti.previous_connectionData == null || !uti.connectionData.clientConnection.status
.equals(uti.previous_connectionData.clientConnection.status)) {
uti.tableItem.setText(0, uti.getConnectionIdentifer());
uti.tableItem.setText(2, uti.getStatusName());
updateConnectionStatusColor(uti);
sort = true;
}
if (uti.hasStatus(ConnectionStatus.ESTABLISHED)) {
sort = updateIndicatorValues(uti, true);
}
}
uti.tableItem.getDisplay();
}
adaptTableWidth();
if (sort) {
fillTable();
if (this.needsSort) {
sortTable();
}
this.table.getParent().layout(true, true);
}
private void createTableItem(final UpdatableTableItem uti) {
uti.tableItem = new TableItem(this.table, SWT.NONE);
uti.tableItem.setText(0, uti.getConnectionIdentifer());
uti.tableItem.setText(1, uti.getConnectionAddress());
uti.tableItem.setText(2, uti.getStatusName());
uti.tableItem.setData("TABLE_ITEM_DATA", uti);
final TableItem[] items = this.table.getItems();
final Iterator<Entry<Long, UpdatableTableItem>> iterator = this.tableMapping.entrySet().iterator();
for (int i = 0; i < items.length; i++) {
final UpdatableTableItem uti = iterator.next().getValue();
uti.update(items[i], this.needsSort);
}
this.needsSort = false;
adaptTableWidth();
this.table.layout(true, true);
}
private void adaptTableWidth() {
@ -179,99 +166,163 @@ public final class ClientConnectionTable {
gridData.heightHint = area.height - BOTTOM_PADDING;
}
private void fillTable() {
if (this.tableMapping.size() > this.table.getItemCount()) {
while (this.tableMapping.size() > this.table.getItemCount()) {
new TableItem(this.table, SWT.NONE);
}
this.needsSort = true;
} else if (this.tableMapping.size() < this.table.getItemCount()) {
while (this.tableMapping.size() < this.table.getItemCount()) {
this.table.getItem(0).dispose();
}
this.needsSort = true;
}
}
private void sortTable() {
System.out.println("************** sortTable");
// final TableItem[] items = this.table.getItems();
// Arrays.sort(items, TABLE_COMPARATOR);
// for (final TableItem item : items) {
// final UpdatableTableItem uti = (UpdatableTableItem) item.getData("TABLE_ITEM_DATA");
// item.dispose();
// createTableItem(uti);
// updateIndicatorValues(uti, false);
// updateConnectionStatusColor(uti);
// }
this.tableMapping = this.tableMapping.entrySet()
.stream()
.sorted((e1, e2) -> e1.getValue().compareTo(e2.getValue()))
.collect(Collectors.toMap(
Entry::getKey,
Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
}
private boolean updateIndicatorValues(final UpdatableTableItem uti, final boolean established) {
boolean sort = false;
for (final IndicatorValue iv : uti.connectionData.indicatorValues) {
final IndicatorData indicatorData = this.indicatorMapping.get(iv.getType());
if (indicatorData != null) {
if (!established && iv.getType() == IndicatorType.LAST_PING) {
uti.tableItem.setText(indicatorData.index, "--");
} else {
uti.tableItem.setText(indicatorData.index, String.valueOf(iv.getValue()));
final Color newColor = this.getColorForValue(indicatorData, iv.getValue());
final Color background = uti.tableItem.getBackground(indicatorData.index);
if (newColor != background) {
uti.tableItem.setBackground(indicatorData.index, newColor);
sort = true;
}
}
}
}
return sort;
}
private void updateConnectionStatusColor(final UpdatableTableItem uti) {
switch (uti.connectionData.clientConnection.status) {
case ESTABLISHED: {
uti.tableItem.setBackground(2, this.color1);
break;
}
case ABORTED: {
uti.tableItem.setBackground(2, this.color3);
break;
}
default: {
uti.tableItem.setBackground(2, this.color2);
}
}
}
private Color getColorForValue(final IndicatorData indicatorData, final double value) {
for (int i = 0; i < indicatorData.thresholdColor.length; i++) {
if (value < indicatorData.thresholdColor[i].value) {
return indicatorData.thresholdColor[i].color;
}
}
return indicatorData.thresholdColor[indicatorData.thresholdColor.length - 1].color;
}
private static final class UpdatableTableItem {
private final class UpdatableTableItem implements Comparable<UpdatableTableItem> {
@SuppressWarnings("unused")
final Long connectionId;
TableItem tableItem;
ClientConnectionData previous_connectionData;
ClientConnectionData connectionData;
private boolean changed = false;
private ClientConnectionData connectionData;
private int[] thresholdColorIndices;
private UpdatableTableItem(final Table parent, final Long connectionId) {
this.tableItem = null;
UpdatableTableItem(final Long connectionId) {
this.connectionId = connectionId;
}
public void update(final TableItem tableItem) {
}
public String getStatusName() {
if (this.connectionData != null && this.connectionData.clientConnection.status != null) {
return this.connectionData.clientConnection.status.name();
void update(final TableItem tableItem, final boolean force) {
if (force || this.changed) {
update(tableItem);
}
return ConnectionStatus.UNDEFINED.name();
this.changed = false;
}
public String getConnectionAddress() {
void update(final TableItem tableItem) {
updateData(tableItem);
if (this.connectionData != null) {
updateConnectionStatusColor(tableItem);
updateIndicatorValues(tableItem);
}
}
void updateData(final TableItem tableItem) {
tableItem.setText(0, getConnectionIdentifer());
tableItem.setText(1, getConnectionAddress());
tableItem.setText(2, getStatusName());
}
void updateConnectionStatusColor(final TableItem tableItem) {
switch (this.connectionData.clientConnection.status) {
case ESTABLISHED: {
tableItem.setBackground(2, ClientConnectionTable.this.color1);
break;
}
case ABORTED: {
tableItem.setBackground(2, ClientConnectionTable.this.color3);
break;
}
default: {
tableItem.setBackground(2, ClientConnectionTable.this.color2);
}
}
}
void updateIndicatorValues(final TableItem tableItem) {
final boolean fillEmpty = (this.connectionData == null ||
this.connectionData.clientConnection.status != ConnectionStatus.ESTABLISHED);
for (int i = 0; i < this.connectionData.indicatorValues.size(); i++) {
final IndicatorValue indicatorValue = this.connectionData.indicatorValues.get(i);
final IndicatorData indicatorData =
ClientConnectionTable.this.indicatorMapping.get(indicatorValue.getType());
if (fillEmpty) {
tableItem.setText(indicatorData.index, Constants.EMPTY_NOTE);
tableItem.setBackground(
indicatorData.index,
indicatorData.defaultColor);
} else {
tableItem.setText(indicatorData.index, String.valueOf(indicatorValue.getValue()));
tableItem.setBackground(
indicatorData.index,
indicatorData.thresholdColor[this.thresholdColorIndices[i]].color);
}
}
}
@Override
public int compareTo(final UpdatableTableItem other) {
return Comparator.comparingInt(UpdatableTableItem::statusWeight)
.thenComparingInt(UpdatableTableItem::thresholdsWeight)
.thenComparing(UpdatableTableItem::getConnectionIdentifer)
.compare(this, other);
}
int statusWeight() {
if (this.connectionData == null) {
return 100;
}
switch (this.connectionData.clientConnection.status) {
case ABORTED:
return 0;
case CONNECTION_REQUESTED:
case AUTHENTICATED:
return 1;
case ESTABLISHED:
return 2;
case CLOSED:
return 3;
default:
return 10;
}
}
int thresholdsWeight() {
if (this.thresholdColorIndices == null) {
return 100;
}
int weight = 0;
for (int i = 0; i < this.thresholdColorIndices.length; i++) {
weight += this.thresholdColorIndices[i];
}
return 100 - weight;
}
String getStatusName() {
String name;
if (this.connectionData != null && this.connectionData.clientConnection.status != null) {
name = this.connectionData.clientConnection.status.name();
} else {
name = ConnectionStatus.UNDEFINED.name();
}
return ClientConnectionTable.this.widgetFactory.getI18nSupport()
.getText(STATUS_LOC_TEXT_KEY_PREFIX + name, name);
}
String getConnectionAddress() {
if (this.connectionData != null && this.connectionData.clientConnection.clientAddress != null) {
return this.connectionData.clientConnection.clientAddress;
}
return Constants.EMPTY_NOTE;
}
public String getConnectionIdentifer() {
String getConnectionIdentifer() {
if (this.connectionData != null && this.connectionData.clientConnection.userSessionId != null) {
return this.connectionData.clientConnection.userSessionId;
}
@ -279,35 +330,71 @@ public final class ClientConnectionTable {
return "--";
}
public boolean hasStatus(final ConnectionStatus status) {
if (this.connectionData != null && this.connectionData.clientConnection != null) {
return status == this.connectionData.clientConnection.status;
void push(final ClientConnectionData connectionData) {
this.changed = this.connectionData == null ||
!this.connectionData.dataEquals(connectionData);
ClientConnectionTable.this.needsSort = this.connectionData == null ||
this.connectionData.clientConnection.status != connectionData.clientConnection.status;
if (this.thresholdColorIndices == null) {
this.thresholdColorIndices = new int[connectionData.indicatorValues.size()];
}
return false;
}
for (int i = 0; i < connectionData.indicatorValues.size(); i++) {
final IndicatorValue indicatorValue = connectionData.indicatorValues.get(i);
final IndicatorData indicatorData =
ClientConnectionTable.this.indicatorMapping.get(indicatorValue.getType());
final double value = indicatorValue.getValue();
final int colorIndex = getColorIndex(indicatorData, value);
if (this.thresholdColorIndices[i] != colorIndex) {
ClientConnectionTable.this.needsSort = true;
}
this.thresholdColorIndices[i] = colorIndex;
}
public void push(final ClientConnectionData connectionData) {
this.previous_connectionData = this.connectionData;
this.connectionData = connectionData;
}
}
private static final int getColorIndex(final IndicatorData indicatorData, final double value) {
for (int j = 0; j < indicatorData.thresholdColor.length; j++) {
if (value < indicatorData.thresholdColor[j].value) {
return j;
}
}
return indicatorData.thresholdColor.length - 1;
}
private static final class IndicatorData {
final int index;
@SuppressWarnings("unused")
final Indicator indicator;
final Color defaultColor;
final ThresholdColor[] thresholdColor;
protected IndicatorData(final Indicator indicator, final int index, final Display display) {
this.indicator = indicator;
this.index = index;
if (StringUtils.isNotBlank(indicator.defaultColor)) {
final RGB rgb = new RGB(
Integer.parseInt(indicator.defaultColor.substring(0, 2), 16),
Integer.parseInt(indicator.defaultColor.substring(2, 4), 16),
Integer.parseInt(indicator.defaultColor.substring(4, 6), 16));
this.defaultColor = new Color(display, rgb, 100);
} else {
this.defaultColor = new Color(display, new RGB(255, 255, 255), 100);
}
this.thresholdColor = new ThresholdColor[indicator.thresholds.size()];
for (int i = 0; i < indicator.thresholds.size(); i++) {
this.thresholdColor[i] = new ThresholdColor(indicator.thresholds.get(i), display);
}
}
}
private static final class ThresholdColor {
@ -316,29 +403,15 @@ public final class ClientConnectionTable {
protected ThresholdColor(final Threshold threshold, final Display display) {
this.value = threshold.value;
final RGB rgb = new RGB(
Integer.parseInt(threshold.color.substring(0, 2), 16),
Integer.parseInt(threshold.color.substring(2, 4), 16),
Integer.parseInt(threshold.color.substring(4, 6), 16));
this.color = new Color(display, rgb, 100);
}
}
private static final Comparator<TableItem> TABLE_COMPARATOR = new Comparator<>() {
@Override
public int compare(final TableItem o1, final TableItem o2) {
final String name1 = o1.getText(0);
final String name2 = o2.getText(0);
if (name1 != null) {
return name1.compareTo(name2);
} else if (name2 != null) {
return name2.compareTo(name1);
if (StringUtils.isNotBlank(threshold.color)) {
final RGB rgb = new RGB(
Integer.parseInt(threshold.color.substring(0, 2), 16),
Integer.parseInt(threshold.color.substring(2, 4), 16),
Integer.parseInt(threshold.color.substring(4, 6), 16));
this.color = new Color(display, rgb, 100);
} else {
return -1;
this.color = new Color(display, new RGB(255, 255, 255), 100);
}
}
};
}
}

View file

@ -4,7 +4,3 @@ server.address=localhost
server.port=8080
server.servlet.context-path=/
#sebserver.webservice.api.redirect.unauthorized=http://localhost:8080/gui