Index: bidspace/pom.xml
===================================================================
--- bidspace/pom.xml	(revision 43)
+++ bidspace/pom.xml	(revision 44)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>bidspace</artifactId>
-	<version>2.0.7</version>
+	<version>2.0.8</version>
 	<packaging>jar</packaging>
 
Index: bidspace/src/main/java/geniusweb/bidspace/pareto/GenericPareto.java
===================================================================
--- bidspace/src/main/java/geniusweb/bidspace/pareto/GenericPareto.java	(revision 43)
+++ bidspace/src/main/java/geniusweb/bidspace/pareto/GenericPareto.java	(revision 44)
@@ -1,4 +1,6 @@
 package geniusweb.bidspace.pareto;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -14,10 +16,11 @@
 /**
  * A set of all pareto points associated with a set of profiles. Generally
- * applicable but slow.
+ * applicable but slow. It is recommended to use {@link ParetoLinearAdditive} if
+ * applicable.
  */
 public class GenericPareto implements ParetoFrontier {
 
 	private final List<? extends PartialOrdering> profiles;
-	private Set<Bid> paretobids = null;
+	private transient Set<Bid> paretobids = null; // cache
 
 	/**
@@ -35,5 +38,5 @@
 					"at least 2 profiles are needed");
 		}
-		if (profiles.stream().anyMatch(profile -> profile == null)) {
+		if (profiles.contains(null)) {
 			throw new IllegalArgumentException("Profiles must not be null");
 		}
@@ -46,10 +49,10 @@
 			}
 		}
-		this.profiles = profiles;
+		this.profiles = new ArrayList<>(profiles);
 	}
 
 	@Override
-	public List<? extends Profile> getProfiles() {
-		return profiles;
+	public List<Profile> getProfiles() {
+		return Collections.unmodifiableList(profiles);
 	}
 
@@ -58,5 +61,5 @@
 		if (paretobids == null)
 			computePareto();
-		return paretobids;
+		return Collections.unmodifiableSet(paretobids);
 	}
 
Index: bidspace/src/main/java/geniusweb/bidspace/pareto/ParetoPoint.java
===================================================================
--- bidspace/src/main/java/geniusweb/bidspace/pareto/ParetoPoint.java	(revision 43)
+++ bidspace/src/main/java/geniusweb/bidspace/pareto/ParetoPoint.java	(revision 44)
@@ -3,11 +3,8 @@
 import java.math.BigDecimal;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import geniusweb.issuevalue.Bid;
-import geniusweb.issuevalue.Value;
 import geniusweb.profile.utilityspace.LinearAdditive;
 
@@ -49,11 +46,4 @@
 	 */
 	public ParetoPoint merge(ParetoPoint otherpoint) {
-		Map<String, Value> issuevalues = new HashMap<>();
-		for (String issue : bid.getIssues()) {
-			issuevalues.put(issue, bid.getValue(issue));
-		}
-		for (String issue : otherpoint.bid.getIssues()) {
-			issuevalues.put(issue, otherpoint.bid.getValue(issue));
-		}
 		List<BigDecimal> summedutils = new LinkedList<>();
 		for (int n = 0; n < utilities.size(); n++) {
@@ -61,5 +51,5 @@
 		}
 
-		return new ParetoPoint(summedutils, new Bid(issuevalues));
+		return new ParetoPoint(summedutils, bid.merge(otherpoint.getBid()));
 	}
 
Index: bidspace/src/test/java/geniusweb/bidspace/pareto/GenericParetoTest.java
===================================================================
--- bidspace/src/test/java/geniusweb/bidspace/pareto/GenericParetoTest.java	(revision 43)
+++ bidspace/src/test/java/geniusweb/bidspace/pareto/GenericParetoTest.java	(revision 44)
@@ -2,10 +2,11 @@
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -14,8 +15,9 @@
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
+import org.junit.Before;
 import org.junit.Test;
 
-import geniusweb.bidspace.pareto.GenericPareto;
 import geniusweb.issuevalue.Bid;
 import geniusweb.issuevalue.DiscreteValue;
@@ -27,4 +29,5 @@
 import geniusweb.issuevalue.ValueSet;
 import geniusweb.profile.PartialOrdering;
+import geniusweb.profile.Profile;
 
 public class GenericParetoTest {
@@ -39,13 +42,17 @@
 	private static final Map<String, ValueSet> issues = new HashMap<>();
 
-	private static final ValueSet values1;
-	private static final ValueSet values2;
+	private static ValueSet values1;
+	private static ValueSet values2;
 	private static final BigDecimal TWO = new BigDecimal("2");
 	private static final BigDecimal THREE = new BigDecimal("3");
 
-	private static final Domain domain;
+	private static Domain domain;
 	private static Bid bid1, bid2, bid3;
 
-	static {
+	private PartialOrdering profile1, profile2, profile3;
+	private GenericPareto pareto;
+
+	@Before
+	public void before() {
 		Collection<DiscreteValue> discretevalues1 = new LinkedList<>();
 		discretevalues1.add(I1V1);
@@ -70,13 +77,17 @@
 		bid3 = new Bid(issuevalues);
 
+		profile1 = mock(PartialOrdering.class);
+		profile2 = mock(PartialOrdering.class);
+		profile3 = mock(PartialOrdering.class);
+		when(profile1.getDomain()).thenReturn(domain);
+		when(profile2.getDomain()).thenReturn(domain);
+		when(profile3.getDomain()).thenReturn(domain);
+
+		pareto = new GenericPareto(Arrays.asList(profile1, profile2));
+
 	}
 
 	@Test
 	public void genericParetoTest() {
-		PartialOrdering profile1 = mock(PartialOrdering.class);
-		PartialOrdering profile2 = mock(PartialOrdering.class);
-
-		when(profile1.getDomain()).thenReturn(domain);
-		when(profile2.getDomain()).thenReturn(domain);
 
 		// fefault: there is no preference at all, all isPreferredOrEqual
@@ -92,9 +103,4 @@
 	@Test
 	public void genericParetoTest1() {
-		PartialOrdering profile1 = mock(PartialOrdering.class);
-		PartialOrdering profile2 = mock(PartialOrdering.class);
-
-		when(profile1.getDomain()).thenReturn(domain);
-		when(profile2.getDomain()).thenReturn(domain);
 
 		// both prefer bid1 over any other bid.
@@ -103,7 +109,4 @@
 		when(profile2.isPreferredOrEqual(eq(bid1), any(Bid.class)))
 				.thenReturn(true);
-
-		List<PartialOrdering> profiles = Arrays.asList(profile1, profile2);
-		GenericPareto pareto = new GenericPareto(profiles);
 
 		Collection<Bid> points = pareto.getPoints();
@@ -114,9 +117,4 @@
 	@Test
 	public void genericParetoTest2() {
-		PartialOrdering profile1 = mock(PartialOrdering.class);
-		PartialOrdering profile2 = mock(PartialOrdering.class);
-
-		when(profile1.getDomain()).thenReturn(domain);
-		when(profile2.getDomain()).thenReturn(domain);
 
 		// both prefer bid2 over any other bid.
@@ -125,6 +123,4 @@
 		when(profile2.isPreferredOrEqual(eq(bid2), any(Bid.class)))
 				.thenReturn(true);
-		List<PartialOrdering> profiles = Arrays.asList(profile1, profile2);
-		GenericPareto pareto = new GenericPareto(profiles);
 
 		Collection<Bid> points = pareto.getPoints();
@@ -136,10 +132,4 @@
 	@Test
 	public void genericParetoTest3() {
-		PartialOrdering profile1 = mock(PartialOrdering.class);
-		PartialOrdering profile2 = mock(PartialOrdering.class);
-
-		when(profile1.getDomain()).thenReturn(domain);
-		when(profile2.getDomain()).thenReturn(domain);
-
 		// profile1 prefers bid1, profile2 prefers bid2.
 		// now neither bid1 nor bid2 are dominating each other
@@ -149,6 +139,4 @@
 		when(profile2.isPreferredOrEqual(eq(bid2), any(Bid.class)))
 				.thenReturn(true);
-		List<PartialOrdering> profiles = Arrays.asList(profile1, profile2);
-		GenericPareto pareto = new GenericPareto(profiles);
 
 		Collection<Bid> points = pareto.getPoints();
@@ -159,9 +147,4 @@
 	@Test
 	public void genericParetoTest4() {
-		PartialOrdering profile1 = mock(PartialOrdering.class);
-		PartialOrdering profile2 = mock(PartialOrdering.class);
-
-		when(profile1.getDomain()).thenReturn(domain);
-		when(profile2.getDomain()).thenReturn(domain);
 
 		// profile1 prefers bid1, profile2 prefers bid2.
@@ -175,6 +158,4 @@
 		when(profile2.isPreferredOrEqual(eq(bid2), any(Bid.class)))
 				.thenReturn(true);
-		List<PartialOrdering> profiles = Arrays.asList(profile1, profile2);
-		GenericPareto pareto = new GenericPareto(profiles);
 
 		Collection<Bid> points = pareto.getPoints();
@@ -183,3 +164,31 @@
 	}
 
+	@Test(expected = IllegalArgumentException.class)
+	public void testNullNotOk() {
+		new GenericPareto(Arrays.asList(profile1, null, profile1));
+	}
+
+	@Test
+	public void testImmutable() {
+		List<PartialOrdering> list = new ArrayList<>(
+				Arrays.asList(profile1, profile2));
+		GenericPareto pareto = new GenericPareto(list);
+		// if we modify the list, the pareto should not change
+		list.add(profile3);
+		assertEquals(2, pareto.getProfiles().size());
+	}
+
+	@Test(expected = UnsupportedOperationException.class)
+	public void testGetParetoAndAdd() {
+		List<Profile> list = pareto.getProfiles();
+		list.add(profile3);
+
+	}
+
+	@Test(expected = UnsupportedOperationException.class)
+	public void testGetPointsAndAdd() {
+		Set<Bid> list = pareto.getPoints();
+		list.add(bid1);
+	}
+
 }
Index: bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoE2Etest.java
===================================================================
--- bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoE2Etest.java	(revision 43)
+++ bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoE2Etest.java	(revision 44)
@@ -36,5 +36,5 @@
 						"src/test/resources/jobs/jobs2.json", 18 },
 				{ "src/test/resources/7issues/7issues1.json",
-						"src/test/resources/7issues/7issues2.json", 351 } });
+						"src/test/resources/7issues/7issues2.json", 557 } });
 	}
 
Index: bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoPointTest.java
===================================================================
--- bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoPointTest.java	(revision 43)
+++ bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoPointTest.java	(revision 44)
@@ -4,5 +4,5 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -10,5 +10,6 @@
 import java.math.BigDecimal;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.junit.Before;
@@ -85,21 +86,15 @@
 	@Test
 	public void mergeTest() {
+		Value value1 = mock(Value.class), value2 = mock(Value.class),
+				value3 = mock(Value.class);
 		// partial bid 020_010 has value 0.2 for issue 2 in space1 and 0.1 for
 		// issue 2 in space2.
-		Bid partialbid020_010 = mock(Bid.class),
-				partialbid102_301 = mock(Bid.class);
+		Bid partialbid020_010 = new Bid("issue2", value2);
+		Map<String, Value> vals2 = new HashMap<>();
+		vals2.put("issue1", value1);
+		vals2.put("issue3", value3);
+		Bid partialbid102_301 = new Bid(vals2);
 		// merged this should be a bid 122_311 so it has utilities
 		// 1+2+2=0.5 in space1 and 3+1+1=0.5 in space2
-
-		when(partialbid020_010.getIssues())
-				.thenReturn(new HashSet<String>(Arrays.asList("issue2")));
-		when(partialbid102_301.getIssues()).thenReturn(
-				new HashSet<String>(Arrays.asList("issue1", "issue3")));
-
-		Value value1 = mock(Value.class), value2 = mock(Value.class),
-				value3 = mock(Value.class);
-		when(partialbid020_010.getValue(eq("issue2"))).thenReturn(value2);
-		when(partialbid102_301.getValue(eq("issue1"))).thenReturn(value1);
-		when(partialbid102_301.getValue(eq("issue3"))).thenReturn(value3);
 
 		when(space1.getUtility(eq(partialbid020_010))).thenReturn(D0_2);
@@ -115,11 +110,4 @@
 		ParetoPoint p = p1.merge(p2);
 		Bid bid = p.getBid();
-		assertEquals(
-				new HashSet<String>(
-						Arrays.asList("issue1", "issue2", "issue3")),
-				bid.getIssues());
-		assertEquals(value1, bid.getValue("issue1"));
-		assertEquals(value2, bid.getValue("issue2"));
-		assertEquals(value3, bid.getValue("issue3"));
 		assertEquals(D0_5, p.getUtilities().get(0));
 		assertEquals(D0_5, p.getUtilities().get(1));
Index: bidspace/src/test/resources/7issues/7issues1.json
===================================================================
--- bidspace/src/test/resources/7issues/7issues1.json	(revision 43)
+++ bidspace/src/test/resources/7issues/7issues1.json	(revision 44)
@@ -9,5 +9,4 @@
 					"highValue": 9,
 					"highUtility": 0.99
-
 				}
 			},
@@ -18,5 +17,4 @@
 					"highValue": 9,
 					"highUtility": 0.97
-
 				}
 			},
@@ -27,5 +25,4 @@
 					"highValue": 9,
 					"highUtility": 0.96
-
 				}
 			},
@@ -36,5 +33,4 @@
 					"highValue": 9,
 					"highUtility": 0.94
-
 				}
 			},
@@ -45,5 +41,4 @@
 					"highValue": 9,
 					"highUtility": 0.93
-
 				}
 			},
@@ -54,5 +49,4 @@
 					"highValue": 9,
 					"highUtility": 0.92
-
 				}
 			},
@@ -63,5 +57,4 @@
 					"highValue": 9,
 					"highUtility": 0.91
-
 				}
 			}
@@ -80,23 +73,23 @@
 			"issuesValues": {
 				"i1": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i2": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i3": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i4": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i5": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i6": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i7": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				}
 			}
Index: bidspace/src/test/resources/7issues/7issues2.json
===================================================================
--- bidspace/src/test/resources/7issues/7issues2.json	(revision 43)
+++ bidspace/src/test/resources/7issues/7issues2.json	(revision 44)
@@ -9,5 +9,4 @@
 					"highValue": 9,
 					"highUtility": 0.11
-
 				}
 			},
@@ -18,5 +17,4 @@
 					"highValue": 9,
 					"highUtility": 0.21
-
 				}
 			},
@@ -27,5 +25,4 @@
 					"highValue": 9,
 					"highUtility": 0.13
-
 				}
 			},
@@ -36,5 +33,4 @@
 					"highValue": 9,
 					"highUtility": 0.14
-
 				}
 			},
@@ -45,5 +41,4 @@
 					"highValue": 9,
 					"highUtility": 0.15
-
 				}
 			},
@@ -54,5 +49,4 @@
 					"highValue": 9,
 					"highUtility": 0.16
-
 				}
 			},
@@ -63,16 +57,15 @@
 					"highValue": 9,
 					"highUtility": 0.17
-
 				}
 			}
 		},
 		"issueWeights": {
-			"i1": 0.24745759773026107,
-			"i2": 0.11824193959921694,
-			"i3": 0.1860471425098606,
-			"i4": 0.20629555826677742,
-			"i5": 0.16112666189388397,
+			"i1": 0.24746,
+			"i2": 0.118241,
+			"i3": 0.186047,
+			"i4": 0.206295,
+			"i5": 0.161126,
 			"i6": 0.0538874,
-			"i7": 0.0269437
+			"i7": 0.0269436
 		},
 		"domain": {
@@ -80,23 +73,23 @@
 			"issuesValues": {
 				"i1": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i2": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i3": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i4": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i5": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i6": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				},
 				"i7": {
-					"range": {"low":0,"high":9,"step":1}
+					"range": {"low":0,"high":9,"step":1} 
 				}
 			}
