Skip to content

Commit

Permalink
Remove commons-collections and add Multimaps
Browse files Browse the repository at this point in the history
  • Loading branch information
yahavi committed Jun 16, 2024
1 parent 6dfb4e9 commit 24eaf56
Show file tree
Hide file tree
Showing 30 changed files with 492 additions and 124 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/integrationTests.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Integration Tests
on:
push:
branches:
- master
# Triggers the workflow on labeled PRs only.
pull_request_target:
types: [ labeled ]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.jfrog.build.api.multiMap;

import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;

/**
* A multimap that uses a {@link LinkedList} to store the values.
*
* @param <Key>
* @param <Value>
*/
public class ListMultimap<Key, Value> extends Multimap<Key, Value> {

/**
* Default constructor.
*/
public ListMultimap() {
super();
}

/**
* Constructor that accepts a map.
*
* @param map the map
*/
public ListMultimap(Map<Key, Value> map) {
super(map);
}

/**
* Put a key-value pair into the multimap.
*
* @param key the key
* @param value the value
*/
public void put(Key key, Value value) {
Collection<Value> currentValue = multiMap.getOrDefault(key, new LinkedList<>());
currentValue.add(value);
multiMap.put(key, currentValue);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package org.jfrog.build.api.multiMap;

import java.io.Serializable;
import java.util.*;

public abstract class Multimap<Key, Value> implements Serializable {
private static final long serialVersionUID = 1L;

Multimap() {
}

Multimap(Map<Key, Value> map) {
map.forEach(this::put);
}

Map<Key, Collection<Value>> multiMap = new HashMap<>();

/**
* Put a key-value pair into the multimap.
*
* @param key the key
* @param value the value
*/
public abstract void put(Key key, Value value);

/**
* Get all values for a key.
*
* @param key the key
* @return a collection of values for the key
*/
public Collection<Value> get(Key key) {
return multiMap.get(key);
}

/**
* Put all key-value pairs from a map into the multimap.
*
* @param map the map
*/
public void putAll(Map<Key, Value> map) {
for (Map.Entry<Key, Value> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}

/**
* Put all key-value pairs from a multimap into the multimap.
*
* @param multimap the multimap
*/
public void putAll(Multimap<Key, Value> multimap) {
for (Map.Entry<Key, Collection<Value>> entry : multimap.multiMap.entrySet()) {
for (Value value : entry.getValue()) {
put(entry.getKey(), value);
}
}
}

/**
* Put all values for a key into the multimap.
*
* @param key the key
* @param values the values
*/
public void putAll(Key key, Collection<Value> values) {
for (Value value : values) {
put(key, value);
}
}

/**
* Get all key-value pairs in the multimap.
*
* @return a set of key-value pairs
*/
public Set<Map.Entry<Key, Value>> entries() {
Set<Map.Entry<Key, Value>> entries = new HashSet<>();
for (Map.Entry<Key, Collection<Value>> entry : multiMap.entrySet()) {
for (Value value : entry.getValue()) {
entries.add(new AbstractMap.SimpleEntry<>(entry.getKey(), value));
}
}
return entries;
}

/**
* Get the underlying map.
*
* @return the map
*/
public Map<Key, Collection<Value>> asMap() {
return multiMap;
}

/**
* Get all keys in the multimap.
*
* @return a set of keys
*/
public Set<Key> keySet() {
return multiMap.keySet();
}

/**
* Check if the multimap contains a value.
*
* @param value the value
* @return true if the multimap contains the value
*/
public boolean containsValue(Value value) {
for (Collection<Value> values : multiMap.values()) {
if (values.contains(value)) {
return true;
}
}
return false;
}

/**
* Get the number of key-value pairs in the multimap.
*
* @return the number of key-value pairs
*/
public int size() {
return multiMap.size();
}

/**
* Check if the multimap is empty.
*
* @return true if the multimap is empty
*/
public boolean isEmpty() {
return multiMap.isEmpty();
}

/**
* Clear the multimap.
*/
public void clear() {
multiMap.clear();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.jfrog.build.api.multiMap;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;

/**
* A multimap that uses a {@link HashSet} to store the values.
*
* @param <Key>
* @param <Value>
*/
public class SetMultimap<Key, Value> extends Multimap<Key, Value> {
public SetMultimap() {
super();
}

public SetMultimap(Map<Key, Value> map) {
super(map);
}

/**
* Put a key-value pair into the multimap.
*
* @param key the key
* @param value the value
*/
public void put(Key key, Value value) {
Collection<Value> currentValue = multiMap.getOrDefault(key, new HashSet<>());
currentValue.add(value);
multiMap.put(key, currentValue);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.jfrog.build.api.multiMap;

import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

@Test
public class ListMultimapTest {

public void testPutDuplicated() {
Multimap<String, String> multimap = new ListMultimap<>();
multimap.put("key", "value");
multimap.put("key", "value");
String[] values = multimap.get("key").toArray(new String[0]);

assertEquals(values.length, 2);
assertEquals(values[0], "value");
assertEquals(values[1], "value");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package org.jfrog.build.api.multiMap;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

public class MultimapTest {

@DataProvider
private Object[][] testCases() {
return new Object[][]{
{new ListMultimap<String, String>()},
{new SetMultimap<String, String>()}
};
}

@Test(dataProvider = "testCases")
public void testPut(Multimap<String, String> multimap) {
multimap.put("key", "value1");
multimap.put("key", "value2");
assertTrue(multimap.get("key").contains("value1"));
assertTrue(multimap.get("key").contains("value2"));
}

@Test(dataProvider = "testCases")
public void testPutAllMultimap(Multimap<String, String> multimap) {
Multimap<String, String> otherMultimap = new ListMultimap<>();
otherMultimap.put("key", "value1");
otherMultimap.put("key", "value2");
multimap.putAll(otherMultimap);
assertTrue(multimap.get("key").contains("value1"));
assertTrue(multimap.get("key").contains("value2"));
}

@Test(dataProvider = "testCases")
public void testPutAllCollection(Multimap<String, String> multimap) {
List<String> otherCollection = new ArrayList<>();
otherCollection.add("value1");
otherCollection.add("value2");
multimap.putAll("key", otherCollection);
assertTrue(multimap.get("key").contains("value1"));
assertTrue(multimap.get("key").contains("value2"));
}

@Test(dataProvider = "testCases")
public void testPutAllMap(Multimap<String, String> multimap) {
Map<String, String> otherMap = new HashMap<>();
otherMap.put("key1", "value1");
otherMap.put("key2", "value2");
multimap.putAll(otherMap);
assertTrue(multimap.get("key1").contains("value1"));
assertTrue(multimap.get("key2").contains("value2"));
}

@Test(dataProvider = "testCases")
public void testEntries(Multimap<String, String> multimap) {
multimap.put("key1", "value1");
multimap.put("key2", "value2");
assertTrue(multimap.entries().contains(new HashMap.SimpleEntry<>("key1", "value1")));
assertTrue(multimap.entries().contains(new HashMap.SimpleEntry<>("key2", "value2")));
}

@Test(dataProvider = "testCases")
public void testAsMap(Multimap<String, String> multimap) {
multimap.put("key1", "value1");
multimap.put("key2", "value2");
assertTrue(multimap.asMap().containsKey("key1"));
assertTrue(multimap.asMap().containsKey("key2"));
}

@Test(dataProvider = "testCases")
public void testKeySet(Multimap<String, String> multimap) {
multimap.put("key1", "value1");
multimap.put("key2", "value2");
assertTrue(multimap.keySet().contains("key1"));
assertTrue(multimap.keySet().contains("key2"));
}

@Test(dataProvider = "testCases")
public void testContainsValue(Multimap<String, String> multimap) {
multimap.put("key1", "value1");
multimap.put("key2", "value2");
assertTrue(multimap.containsValue("value1"));
assertTrue(multimap.containsValue("value2"));
}

@Test(dataProvider = "testCases")
public void testSize(Multimap<String, String> multimap) {
multimap.put("key1", "value1");
multimap.put("key2", "value2");
assertEquals(multimap.size(), 2);
}

@Test(dataProvider = "testCases")
public void testIsEmpty(Multimap<String, String> multimap) {
assertTrue(multimap.isEmpty());
}

@Test(dataProvider = "testCases")
public void testClear(Multimap<String, String> multimap) {
multimap.put("key1", "value1");
multimap.put("key2", "value2");
multimap.clear();
assertTrue(multimap.isEmpty());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.jfrog.build.api.multiMap;

import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

@Test
public class SetMultimapTest {

public void testPutDuplicated() {
Multimap<String, String> multimap = new SetMultimap<>();
multimap.put("key", "value");
multimap.put("key", "value");
String[] values = multimap.get("key").toArray(new String[0]);

assertEquals(values.length, 1);
assertEquals(values[0], "value");
}
}
Loading

0 comments on commit 24eaf56

Please sign in to comment.