Skip to content

Commit

Permalink
Typify MultiValueMap and fix warnings in AutomaticRouter (eclipse-gef…
Browse files Browse the repository at this point in the history
…#320)

The MultiValueMap used to be backed by a map with either a list or a
single object as value.

This part has been adapted so that the map always contains a list of
values. While this adds a small overhead when filling the map, it should
in return reduce the overhead when calling the getter for values with
only a single element.

Reduces the total amount of warnings by ~20.
  • Loading branch information
ptziegler authored Dec 15, 2023
1 parent c2be6d8 commit 98a6240
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 61 deletions.
16 changes: 8 additions & 8 deletions org.eclipse.draw2d/src/org/eclipse/draw2d/AutomaticRouter.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* Copyright (c) 2000, 2023 IBM Corporation and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
Expand All @@ -12,7 +12,7 @@
*******************************************************************************/
package org.eclipse.draw2d;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
Expand All @@ -31,7 +31,7 @@
public abstract class AutomaticRouter extends AbstractRouter {

private ConnectionRouter nextRouter;
private MultiValueMap connections = new MultiValueMap();
private final MultiValueMap<HashKey, Connection> connections = new MultiValueMap<>();

private static final class HashKey {

Expand Down Expand Up @@ -105,11 +105,11 @@ public void invalidate(Connection conn) {
if (conn.getSourceAnchor() == null || conn.getTargetAnchor() == null)
return;
HashKey connectionKey = new HashKey(conn);
ArrayList connectionList = connections.get(connectionKey);
List<Connection> connectionList = connections.get(connectionKey);
int affected = connections.remove(connectionKey, conn);
if (affected != -1) {
for (int i = affected; i < connectionList.size(); i++)
((Connection) connectionList.get(i)).revalidate();
connectionList.get(i).revalidate();
} else
connections.removeValue(conn);

Expand All @@ -133,11 +133,11 @@ public void remove(Connection conn) {
if (conn.getSourceAnchor() == null || conn.getTargetAnchor() == null)
return;
HashKey connectionKey = new HashKey(conn);
ArrayList connectionList = connections.get(connectionKey);
List<Connection> connectionList = connections.get(connectionKey);
if (connectionList != null) {
int index = connections.remove(connectionKey, conn);
for (int i = index + 1; i < connectionList.size(); i++)
((Connection) connectionList.get(i)).revalidate();
connectionList.get(i).revalidate();
}
if (next() != null)
next().remove(conn);
Expand All @@ -162,7 +162,7 @@ public void route(Connection conn) {
if (conn.getPoints().size() == 2) {
PointList points = conn.getPoints();
HashKey connectionKey = new HashKey(conn);
ArrayList connectionList = connections.get(connectionKey);
List<Connection> connectionList = connections.get(connectionKey);

if (connectionList != null) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* Copyright (c) 2000, 2023 IBM Corporation and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
Expand All @@ -16,73 +16,48 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class MultiValueMap {
private HashMap map = new HashMap();
public class MultiValueMap<U, V> {
private final Map<U, List<V>> map = new HashMap<>();

public ArrayList get(Object key) {
Object value = map.get(key);
if (value == null)
return null;

if (value instanceof ArrayList)
return (ArrayList) value;
ArrayList v = new ArrayList(1);
v.add(value);
return v;
public List<V> get(Object key) {
return map.get(key);
}

public void put(Object key, Object value) {
Object existingValues = map.get(key);
if (existingValues == null) {
map.put(key, value);
return;
}
if (existingValues instanceof ArrayList v) {
if (!v.contains(value))
v.add(value);
return;
}
if (existingValues != value) {
ArrayList v = new ArrayList(2);
v.add(existingValues);
v.add(value);
map.put(key, v);
public void put(U key, V value) {
List<V> values = map.computeIfAbsent(key, ignored -> new ArrayList<>(1));
if (!values.contains(value)) {
values.add(value);
}
}

public int remove(Object key, Object value) {
Object existingValues = map.get(key);
if (existingValues != null) {
if (existingValues instanceof ArrayList v) {
int result = v.indexOf(value);
if (result == -1)
return -1;
v.remove(result);
if (v.isEmpty())
map.remove(key);
return result;
public int remove(U key, V value) {
List<V> values = map.get(key);
if (values != null) {
int position = values.indexOf(value);
if (position == -1) {
return -1;
}
if (map.remove(key) != null)
return 0;
values.remove(position);
if (values.isEmpty()) {
map.remove(key);
}
return position;
}
return -1;
}

public Object removeValue(Object value) {
Iterator iter = map.values().iterator();
Object current;
public V removeValue(V value) {
Iterator<List<V>> iter = map.values().iterator();
List<V> current;
while (iter.hasNext()) {
current = iter.next();
if (value.equals(current)) {
iter.remove();
return value;
} else if (current instanceof List) {
if (((List) current).remove(value)) {
if (((List) current).isEmpty())
iter.remove();
return value;
if (current.remove(value)) {
if (current.isEmpty()) {
iter.remove();
}
return value;
}
}
return null;
Expand Down

0 comments on commit 98a6240

Please sign in to comment.