Index: /bidspace/pom.xml
===================================================================
--- /bidspace/pom.xml	(revision 48)
+++ /bidspace/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>bidspace</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -43,5 +43,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
@@ -105,4 +105,10 @@
 			<artifactId>junit</artifactId>
 			<version>1.0.5</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.openjdk.jol</groupId>
+			<artifactId>jol-core</artifactId>
+			<version>0.16</version>
 			<scope>test</scope>
 		</dependency>
@@ -120,5 +126,5 @@
 		</repository>
 	</repositories>
-	
+
 	<pluginRepositories>
 		<pluginRepository>
Index: /bidspace/src/main/java/geniusweb/bidspace/BidsWithUtility.java
===================================================================
--- /bidspace/src/main/java/geniusweb/bidspace/BidsWithUtility.java	(revision 48)
+++ /bidspace/src/main/java/geniusweb/bidspace/BidsWithUtility.java	(revision 49)
@@ -39,4 +39,5 @@
 	 */
 	private final Map<Tuple<Integer, Interval>, ImmutableList<Bid>> cache = new HashMap<>();
+	private ImmutableList<Bid> emptylist = new FixedList<>();
 
 	/**
@@ -135,4 +136,29 @@
 	 * Create partial BidsWithUtil list considering only issues 0..n, with
 	 * utilities in given range.
+	 * <h2>Memory use</h2> Memory use of the return value can be large, if large
+	 * domains are given and the requested interval contains large numbers of
+	 * bids. To give some idea, here are some typical memory uses:
+	 * <table border="1">
+	 * <tr>
+	 * <td>domain</td>
+	 * <td>mem use (MB) of returned object</td>
+	 * <td>nr. of selected bids</td>
+	 * </tr>
+	 * <tr>
+	 * <td>jobs1</td>
+	 * <td>0.028</td>
+	 * <td>23</td>
+	 * </tr>
+	 * <tr>
+	 * <td>7issues1</td>
+	 * <td>34</td>
+	 * <td>346327</td>
+	 * </tr>
+	 * <tr>
+	 * <td>9issues1</td>
+	 * <td>98</td>
+	 * <td>37160666</td>
+	 * </tr>
+	 * </table>
 	 * 
 	 * @param n    the number of issueRanges to consider, we consider 0..n here.
@@ -178,5 +204,5 @@
 		IssueInfo info = issueInfo.get(n);
 		// issue is the first issuesWithRange.
-		String issue = issueInfo.get(n).getName();
+		String issue = info.getName();
 
 		if (n == 0)
@@ -184,5 +210,5 @@
 
 		// make new list, joining all sub-lists
-		ImmutableList<Bid> fulllist = new FixedList<>();
+		ImmutableList<Bid> fulllist = emptylist;
 		for (Value val : info.getValues()) {
 			BigDecimal weightedutil = info.getWeightedUtil(val);
@@ -191,7 +217,6 @@
 			ImmutableList<Bid> partialbids = get(n - 1, subgoal);
 
-			Bid bid = new Bid(issue, val);
 			ImmutableList<Bid> fullbids = new MapList<Bid, Bid>(
-					pbid -> pbid.merge(bid), partialbids);
+					pbid -> pbid.merge(new Bid(issue, val)), partialbids);
 			if (!fullbids.size().equals(BigInteger.ZERO))
 				fulllist = new JoinedList<Bid>(fullbids, fulllist);
Index: /bidspace/src/test/java/geniusweb/bidspace/BidsWithUtilityTest.java
===================================================================
--- /bidspace/src/test/java/geniusweb/bidspace/BidsWithUtilityTest.java	(revision 48)
+++ /bidspace/src/test/java/geniusweb/bidspace/BidsWithUtilityTest.java	(revision 49)
@@ -33,4 +33,5 @@
 	private long expectedSize;
 	private int accuracy = 5;
+	private final static Runtime r = Runtime.getRuntime();
 
 	@Parameters
@@ -102,12 +103,52 @@
 		BigInteger domainsize = new AllBidsList(profile.getDomain()).size();
 
+		long presize = usedMemory();
 		long start = System.currentTimeMillis();
 		BidsWithUtility body = new BidsWithUtility(profile, accuracy);
 		ImmutableList<Bid> list = body.getBids(utilityGoal);
 		long end = System.currentTimeMillis();
+		long postsize = usedMemory();
 		System.out.println("run time: " + (end - start) / 1000. + "s");
-		System.out.println("Total size of bidspace:" + domainsize);
-		System.out.println("Result size: " + list.size());
+		System.out.println("Total size of complete domain:" + domainsize);
+		System.out.println("size of selection: " + list.size());
+		System.out.println("Memory use of selection(MB):"
+				+ (double) (postsize - presize) / (1024 * 1024));
 	}
 
+	/**
+	 * see https://www.geeksforgeeks.org/java-lang-runtime-class-in-java/
+	 * 
+	 * @return currently used memory after doing GC.
+	 * 
+	 */
+	public static long usedMemory() {
+		for (int n = 0; n < 4; n++)
+			gc1(); // repeat as gct seems getting more agressive then
+		return used();
+	}
+
+	/**
+	 * 
+	 * @return used heap mem. Does NOT GC. Uses {@link Runtime#totalMemory()}
+	 *         and {@link Runtime#freeMemory()} to avoid problems when JVM gets
+	 *         more system memory which can happen at any time.
+	 */
+	private static long used() {
+		return r.totalMemory() - r.freeMemory();
+	}
+
+	/**
+	 * repeat garbage collection till heap memory gets stable
+	 */
+	private static void gc1() {
+		long usedMem1 = used(), usedMem2 = Long.MAX_VALUE;
+		for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i) {
+			r.runFinalization();
+			r.gc();
+			Thread.currentThread().yield();
+
+			usedMem2 = usedMem1;
+			usedMem1 = used();
+		}
+	}
 }
Index: /boa/pom.xml
===================================================================
--- /boa/pom.xml	(revision 48)
+++ /boa/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>boa</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /boa/src/main/java/geniusweb/boa/BoaParty.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/BoaParty.java	(revision 48)
+++ /boa/src/main/java/geniusweb/boa/BoaParty.java	(revision 49)
@@ -106,5 +106,6 @@
 	 * @param paramname  the name of the parameter in parameters that contains
 	 *                   the class reference, shoul dbe full.clsss.path
-	 * @param clazz      the class object to load
+	 * @param clazz      the class type to load. Only instances of clazz are
+	 *                   allowed to be returned.
 	 * @param parameters the parameterlist
 	 * @return object of T, loaded from the parameter with paramname
@@ -122,5 +123,7 @@
 		Class<?> c;
 		try {
-			c = Class.forName((String) parameters.get(paramname));
+			// Critical: following must NOT execute any class code.
+			c = this.getClass().getClassLoader()
+					.loadClass((String) parameters.get(paramname));
 		} catch (ClassNotFoundException e) {
 			throw new InstantiationFailedException("Unknown BOA component", e);
Index: /boa/src/test/java/geniusweb/boa/BoaPartyTest.java
===================================================================
--- /boa/src/test/java/geniusweb/boa/BoaPartyTest.java	(revision 48)
+++ /boa/src/test/java/geniusweb/boa/BoaPartyTest.java	(revision 49)
@@ -9,4 +9,5 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import java.io.IOException;
@@ -132,4 +133,34 @@
 	}
 
+	@Test(expected = InstantiationFailedException.class)
+	public void loadClassSecurityTest() throws InstantiationFailedException {
+		BoaParty boa = new BoaParty();
+		Settings settings = mock(Settings.class);
+		Parameters parameters = new Parameters().with("om", "bla");
+		when(settings.getParameters()).thenReturn(parameters);
+		boa.getOpponentModel(settings);
+	}
+
+	@Test(expected = InstantiationFailedException.class)
+	public void loadClassSecurityTest2() throws InstantiationFailedException {
+		BoaParty boa = new BoaParty();
+		Settings settings = mock(Settings.class);
+		Parameters parameters = new Parameters().with("om",
+				"geniusweb.boa.acceptancestrategy.TimeDependentAcceptanceStrategy");
+		when(settings.getParameters()).thenReturn(parameters);
+		boa.getOpponentModel(settings);
+	}
+
+	@Test(expected = InstantiationFailedException.class)
+	public void loadClassSecurityTestCrashingClass()
+			throws InstantiationFailedException {
+		BoaParty boa = new BoaParty();
+		Settings settings = mock(Settings.class);
+		Parameters parameters = new Parameters().with("om",
+				"geniusweb.boa.CrashingClass");
+		when(settings.getParameters()).thenReturn(parameters);
+		boa.getOpponentModel(settings);
+	}
+
 	private BoaParty getInitializedBoa() throws URISyntaxException {
 		BoaParty boa = new BoaParty();
Index: /boa/src/test/java/geniusweb/boa/CrashingClass.java
===================================================================
--- /boa/src/test/java/geniusweb/boa/CrashingClass.java	(revision 49)
+++ /boa/src/test/java/geniusweb/boa/CrashingClass.java	(revision 49)
@@ -0,0 +1,15 @@
+package geniusweb.boa;
+
+/**
+ * Class that throws the moment you try to load the class, even before you make
+ * an instance.
+ *
+ */
+public class CrashingClass {
+	private static int throwfailure = err();
+
+	private static int err() {
+		throw new IllegalArgumentException(
+				"Even loading this class will crash your app");
+	}
+}
Index: /boa/src/test/java/geniusweb/boa/CrashingClassTest.java
===================================================================
--- /boa/src/test/java/geniusweb/boa/CrashingClassTest.java	(revision 49)
+++ /boa/src/test/java/geniusweb/boa/CrashingClassTest.java	(revision 49)
@@ -0,0 +1,29 @@
+package geniusweb.boa;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class CrashingClassTest {
+	private static final String CRASHINGCLASSPATH = "geniusweb.boa.CrashingClass";
+
+	@Test(expected = ExceptionInInitializerError.class)
+	public void testForNameCrashes() throws ClassNotFoundException {
+		// forName DOES run the static code.
+		Class<?> clazz = Class.forName(CRASHINGCLASSPATH);
+	}
+
+	@Test
+	public void testLoadCrashes() throws ClassNotFoundException {
+		// loadClass does NOT run the static code.
+		Class<?> clazz = this.getClass().getClassLoader()
+				.loadClass(CRASHINGCLASSPATH);
+		assertTrue(clazz.isAssignableFrom(CrashingClass.class));
+	}
+
+	@Test
+	public void testImportCrashes() {
+		// refering to crashing class does NOT trigger the static code
+		Class<CrashingClass> clazz = CrashingClass.class;
+	}
+}
Index: /collectparties.sh
===================================================================
--- /collectparties.sh	(revision 48)
+++ /collectparties.sh	(revision 49)
@@ -7,5 +7,5 @@
 rm -rf collectedparties
 mkdir collectedparties
-VERSION=2.1.3
+VERSION=2.1.4
 
 cp "exampleparties/anac2019/agentgg/target/agentgg-${VERSION}-jar-with-dependencies.jar" collectedparties
Index: /domaineditor/pom.xml
===================================================================
--- /domaineditor/pom.xml	(revision 49)
+++ /domaineditor/pom.xml	(revision 49)
@@ -0,0 +1,287 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>geniusweb</groupId>
+	<artifactId>domaineditor</artifactId>
+	<version>2.1.4</version>
+	<packaging>jar</packaging>
+
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<maven.compiler.target>1.8</maven.compiler.target>
+		<maven.compiler.source>1.8</maven.compiler.source>
+		<basedir>.</basedir>
+		<passwd>${env.ARTIFACTORY_PASS}</passwd>
+		<jackson-2-version>2.12.3</jackson-2-version>
+		<geniusweb.version>${project.version}</geniusweb.version>
+	</properties>
+
+	<distributionManagement>
+		<repository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</repository>
+	</distributionManagement>
+
+	<repositories>
+		<repository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+	</repositories>
+
+	<pluginRepositories>
+		<pluginRepository>
+			<id>central</id>
+			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
+	</pluginRepositories>
+
+
+	<dependencies>
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>utilities</artifactId>
+			<version>1.2.1</version>
+		</dependency>
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>logging</artifactId>
+			<version>1.0.1</version>
+		</dependency>
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>mvc</artifactId>
+			<version>1.1.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>issuevalue</artifactId>
+			<version>${geniusweb.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>profile</artifactId>
+			<version>${geniusweb.version}</version>
+		</dependency>
+
+		<!-- the core, which includes Streaming API, shared low-level abstractions 
+			(but NOT data-binding) -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-core</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+
+		<!-- Just the annotations; use this dependency if you want to attach annotations 
+			to classes without connecting them to the code. -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-annotations</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+
+		<!-- databinding; ObjectMapper, JsonNode and related classes are here -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+
+		<!-- smile (binary JSON). Other artifacts in this group do other formats. -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.dataformat</groupId>
+			<artifactId>jackson-dataformat-smile</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+		<!-- JAX-RS provider -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.jaxrs</groupId>
+			<artifactId>jackson-jaxrs-json-provider</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+		<!-- Support for JAX-B annotations as additional configuration -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.module</groupId>
+			<artifactId>jackson-module-jaxb-annotations</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.12</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>junit</artifactId>
+			<version>1.0.5</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+
+
+	<build>
+
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-enforcer-plugin</artifactId>
+				<version>3.0.0-M2</version>
+				<executions>
+					<execution>
+						<id>enforce</id>
+						<configuration>
+							<rules>
+								<dependencyConvergence />
+							</rules>
+						</configuration>
+						<goals>
+							<goal>enforce</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.8.0</version>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-source-plugin</artifactId>
+				<version>3.1.0</version>
+				<executions>
+					<execution>
+						<id>attach-sources</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>3.2.0</version>
+				<executions>
+					<execution>
+						<id>attach-javadocs</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.jfrog.buildinfo</groupId>
+				<artifactId>artifactory-maven-plugin</artifactId>
+				<version>3.2.3</version>
+				<executions>
+					<execution>
+						<id>build-info</id>
+						<goals>
+							<goal>publish</goal>
+						</goals>
+						<configuration>
+							<publisher>
+								<contextUrl>http://artifactory.ewi.tudelft.nl/artifactory</contextUrl>
+								<repoKey>libs-release</repoKey>
+								<username>wouter</username>
+								<password>${passwd}</password>
+							</publisher>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.4.1</version>
+				<configuration>
+					<!-- get all project dependencies -->
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+					<archive>
+						<manifest>
+							<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+							<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+						</manifest>
+					</archive>
+				</configuration>
+				<executions>
+					<execution>
+						<id>make-assembly</id>
+						<!-- bind to the packaging phase -->
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+
+		</plugins>
+
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>org.eclipse.m2e</groupId>
+					<artifactId>lifecycle-mapping</artifactId>
+					<version>1.0.0</version>
+					<configuration>
+						<lifecycleMappingMetadata>
+							<pluginExecutions>
+								<pluginExecution>
+									<pluginExecutionFilter>
+										<groupId>org.jfrog.buildinfo</groupId>
+										<artifactId>artifactory-maven-plugin</artifactId>
+										<versionRange>[1.0.0,)</versionRange>
+										<goals>
+											<goal>publish</goal>
+										</goals>
+									</pluginExecutionFilter>
+									<action>
+										<ignore />
+									</action>
+								</pluginExecution>
+							</pluginExecutions>
+						</lifecycleMappingMetadata>
+					</configuration>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+
+
+	</build>
+
+</project>
Index: /domaineditor/src/main/java/geniusweb/actions/GuiAction.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/actions/GuiAction.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/actions/GuiAction.java	(revision 49)
@@ -0,0 +1,21 @@
+package geniusweb.actions;
+
+import javax.swing.AbstractAction;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import tudelft.utilities.logging.Reporter;
+
+/**
+ * AbstractAction with some more general support and tools
+ */
+public abstract class GuiAction extends AbstractAction {
+	protected final static ObjectMapper jackson = new ObjectMapper();
+	protected final Reporter log;
+
+	public GuiAction(String name, Reporter log) {
+		super(name);
+		this.log = log;
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/actions/LoadAction.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/actions/LoadAction.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/actions/LoadAction.java	(revision 49)
@@ -0,0 +1,52 @@
+package geniusweb.actions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Level;
+
+import javax.swing.JFileChooser;
+import javax.swing.KeyStroke;
+import javax.swing.filechooser.FileNameExtensionFilter;
+
+import geniusweb.domaineditor.ProfileEditor;
+import geniusweb.domaineditor.model.profile.LinearAdditiveUtilitySpaceModel;
+import geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace;
+import tudelft.utilities.logging.Reporter;
+
+public class LoadAction extends GuiAction {
+
+	public LoadAction(Reporter log) {
+		super("Open", log);
+		putValue(SHORT_DESCRIPTION, "Load the profile");
+		putValue(ACCELERATOR_KEY,
+				KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		load(ProfileEditor.getInstance().getModel());
+	}
+
+	public void load(LinearAdditiveUtilitySpaceModel model) {
+		JFileChooser chooser = new JFileChooser();
+		FileNameExtensionFilter filter = new FileNameExtensionFilter(
+				"JSON file", "json");
+		chooser.setFileFilter(filter);
+		int selection = chooser.showOpenDialog(null);
+		if (selection != JFileChooser.APPROVE_OPTION)
+			return;
+		File file = chooser.getSelectedFile();
+
+		try {
+			LinearAdditiveUtilitySpace profi = jackson.readValue(file,
+					LinearAdditiveUtilitySpace.class);
+			model.setCurrentValue(profi);
+		} catch (IOException e1) {
+			log.log(Level.WARNING,
+					"Failed to read file " + file + ": " + e1.getMessage());
+			e1.printStackTrace();
+		}
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/actions/SaveAction.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/actions/SaveAction.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/actions/SaveAction.java	(revision 49)
@@ -0,0 +1,55 @@
+package geniusweb.actions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Level;
+
+import javax.swing.JFileChooser;
+import javax.swing.KeyStroke;
+import javax.swing.filechooser.FileNameExtensionFilter;
+
+import geniusweb.domaineditor.ProfileEditor;
+import geniusweb.domaineditor.model.profile.LinearAdditiveUtilitySpaceModel;
+import geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace;
+import tudelft.utilities.logging.Reporter;
+
+public class SaveAction extends GuiAction {
+
+	public SaveAction(Reporter log) {
+		super("Save", log);
+		putValue(SHORT_DESCRIPTION, "Save the profile");
+		putValue(ACCELERATOR_KEY,
+				KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		save(ProfileEditor.getInstance().getModel());
+	}
+
+	/**
+	 * Save a model.
+	 * 
+	 * @param model the {@link LinearAdditiveUtilitySpaceModel} to be saved
+	 */
+	protected void save(LinearAdditiveUtilitySpaceModel model) {
+		LinearAdditiveUtilitySpace profile = model.getCurrentValue();
+		JFileChooser chooser = new JFileChooser();
+		chooser.setSelectedFile(new File(profile.getName() + ".json"));
+		FileNameExtensionFilter filter = new FileNameExtensionFilter(
+				"JSON file", "json");
+		chooser.setFileFilter(filter);
+		int selection = chooser.showSaveDialog(null);
+		if (selection != JFileChooser.APPROVE_OPTION)
+			return;
+		File file = chooser.getSelectedFile();
+		try {
+			jackson.writeValue(file, profile);
+		} catch (IOException e) {
+			log.log(Level.WARNING, "Failed to save:" + e.getMessage());
+			e.printStackTrace();
+		}
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/ProfileEditor.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/ProfileEditor.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/ProfileEditor.java	(revision 49)
@@ -0,0 +1,80 @@
+package geniusweb.domaineditor;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+
+import geniusweb.actions.LoadAction;
+import geniusweb.actions.SaveAction;
+import geniusweb.domaineditor.model.DomainModel;
+import geniusweb.domaineditor.model.profile.LinearAdditiveUtilitySpaceModel;
+import geniusweb.domaineditor.panels.profile.ProfileEditorPanel;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.panels.PopupReporter;
+
+/**
+ * A profile editor. Contains components to edit domain, reservation bid,
+ * utilities etc.
+ */
+@SuppressWarnings("serial")
+public class ProfileEditor extends JFrame {
+	private final Reporter log;
+	private final LinearAdditiveUtilitySpaceModel model;
+	private static ProfileEditor instance = null;
+
+	private ProfileEditor() {
+		log = new PopupReporter(this);
+		model = getSampleModel();
+		setLayout(new BorderLayout());
+		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+		Reporter log = new PopupReporter(this);
+
+		getContentPane().add(new ProfileEditorPanel(model, log),
+				BorderLayout.CENTER);
+		setJMenuBar(menu());
+
+		pack();
+		setVisible(true);
+	}
+
+	private JMenuBar menu() {
+		JMenuBar mb = new JMenuBar();
+		JMenu filemenu = new JMenu("File");
+		filemenu.add(new LoadAction(log));
+		filemenu.add(new SaveAction(log));
+
+		mb.add(filemenu);
+		JMenu helpmenu = new JMenu("Help");
+		mb.add(helpmenu);
+		return mb;
+
+	}
+
+	private LinearAdditiveUtilitySpaceModel getSampleModel() {
+		DomainModel domain = new DomainModel(log);
+		LinearAdditiveUtilitySpaceModel lamodel = new LinearAdditiveUtilitySpaceModel(
+				domain, log);
+		return lamodel;
+	}
+
+	public static void main(String[] args) {
+		getInstance();
+	}
+
+	public static ProfileEditor getInstance() {
+		if (instance == null)
+			instance = new ProfileEditor();
+		return instance;
+	}
+
+	/**
+	 * .
+	 * 
+	 * @return Currently active model
+	 */
+	public LinearAdditiveUtilitySpaceModel getModel() {
+		return model;
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/BidModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/BidModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/BidModel.java	(revision 49)
@@ -0,0 +1,176 @@
+package geniusweb.domaineditor.model;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.stream.Collectors;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.NumberValue;
+import geniusweb.issuevalue.Value;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.BasicModel;
+import tudelft.utilities.mvc.model.DefaultSelectionModel;
+import tudelft.utilities.mvc.model.ListModel;
+import tudelft.utilities.mvc.model.MapFromKeys;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.SelectionModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.model.TypedModel;
+import tudelft.utilities.mvc.model.events.Added;
+import tudelft.utilities.mvc.model.events.Changed;
+import tudelft.utilities.mvc.model.events.Event;
+import tudelft.utilities.mvc.model.events.Removed;
+
+/**
+ * contains modifyable {@link Bid} with values for all issues in the original
+ * domain. Automatically adapts to changes in the {@link DomainModel}.
+ * 
+ * BidModel implements MapModel. However add and delete operations are not
+ * allowed. That's because we do not want to modify the domain from here.
+ * 
+ * <br>
+ * FIXME this implementation probably can be done much cleaner with
+ * {@link MapFromKeys}
+ *
+ */
+public class BidModel extends DefaultListenable<Event> implements
+		MapModel<StringModel, SelectionModel<BasicModel>>, TypedModel<Bid> {
+	private final MapModel<StringModel, ValueSetModel> issuevalues;
+	private final Map<StringModel, SelectionModel<BasicModel>> selections = new HashMap<>();
+	private final Reporter log;
+
+	/**
+	 * 
+	 * @param issuevalues the map with issue values from
+	 *                    {@link DomainModel#getIssuesModel()}
+	 */
+	public BidModel(MapModel<StringModel, ValueSetModel> issuevalues,
+			Reporter log) {
+		if (log == null || issuevalues == null)
+			throw new NullPointerException();
+		this.issuevalues = issuevalues;
+		this.log = log;
+		ListModel<StringModel> keys = issuevalues.getKeys();
+		for (int n = 0; n < keys.getSize(); n++) {
+			StringModel key = keys.get(n);
+			add(key, issuevalues.getValue(key).getList());
+		}
+		issuevalues.addListener((e) -> handleChange(e));
+
+		// user's changes to the issuevalues are inconsequential
+	}
+
+	private void add(StringModel key, ListModel value) {
+		selections.put(key, new DefaultSelectionModel(value));
+	}
+
+	/**
+	 * Domain change occured. Handle it.
+	 */
+	private void handleChange(Event e) {
+		// we only handle add/remove of issues. If a value is removed,
+		// this should automatically reflect into the selectionmodel.
+		if (!(e instanceof Changed)) {
+			System.out.println("Unexpected event " + e);
+			return;
+		}
+		e = e.getChildEvent();
+		if (e instanceof Removed) {
+			// an issue was removed.
+			selections.remove(e.getSource());
+		} else if (e instanceof Added) {
+			StringModel issuemodel = (StringModel) e.getSource();
+			add(issuemodel, issuevalues.getValue(issuemodel).getList());
+		} else
+			System.out.println("Ignored event " + e);
+		notifyListeners(e);
+	}
+
+	@Override
+	public SelectionModel getValue(StringModel key) {
+		return selections.get(key);
+	}
+
+	@Override
+	public void put(StringModel key, SelectionModel val) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void remove(StringModel key) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public ListModel<StringModel> getKeys() {
+		return issuevalues.getKeys();
+	}
+
+	@Override
+	public int getMinimumSize() {
+		return 1;
+	}
+
+	@Override
+	public String getColumnName(int n) {
+		return n == 0 ? "issue" : "value";
+	}
+
+	@Override
+	public Bid getCurrentValue() throws IllegalStateException {
+		Map<String, Value> selectionmap = selections.entrySet().stream()
+				.collect(Collectors.toMap(entry -> entry.getKey().getValue(),
+						entry -> getVal(entry)));
+		return new Bid(selectionmap);
+	}
+
+	@Override
+	public void setCurrentValue(Bid bid) throws IllegalArgumentException {
+		ListModel<StringModel> issues = issuevalues.getKeys();
+		for (int n = 0; n < issues.getSize(); n++) {
+			StringModel issuemodel = issues.get(n);
+			String issue = issuemodel.getValue();
+			Value val = bid.getValue(issue);
+			if (val == null) {
+				log.log(Level.WARNING,
+						"Bid does not contain value for the issue " + issue);
+				continue;
+			}
+			ValueSetModel values = issuevalues.getValue(issues.get(n));
+			// now find & select the current model containing val
+			boolean isSet = false;
+			for (int v = 0; v < values.getList().getSize(); v++) {
+				BasicModel valuem = values.getList().get(v);
+				if (valuem.getValue().equals(val.getValue())) {
+					selections.get(issuemodel).setSelection(valuem);
+					isSet = true;
+				}
+			}
+			if (!isSet)
+				log.log(Level.WARNING,
+						"Ignoring unknown value " + val + " in bid " + bid);
+		}
+	}
+
+	private Value getVal(Entry<StringModel, SelectionModel<BasicModel>> entry) {
+		Object val = entry.getValue().getSelection().getValue();
+		if (val instanceof String)
+			return new DiscreteValue((String) val);
+		if (val instanceof BigDecimal)
+			return new NumberValue((BigDecimal) val);
+		throw new IllegalStateException(
+				"Value " + val + " is not string or number");
+
+	}
+
+	@Override
+	public SelectionModel<BasicModel> create(StringModel key) {
+		throw new UnsupportedOperationException();
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/DiscreteValueSetModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/DiscreteValueSetModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/DiscreteValueSetModel.java	(revision 49)
@@ -0,0 +1,87 @@
+package geniusweb.domaineditor.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.DiscreteValueSet;
+import geniusweb.issuevalue.ValueSet;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.BasicModel;
+import tudelft.utilities.mvc.model.DefaultListModel;
+import tudelft.utilities.mvc.model.ListModel;
+import tudelft.utilities.mvc.model.StringModel;
+
+/**
+ * Model for a {@link DiscreteValueSet}. This is basically a
+ * ListModel<StringModel>. However the list can never be empty, there must be
+ * always at least 1 value.
+ */
+public class DiscreteValueSetModel extends DefaultListModel<StringModel>
+		implements ValueSetModel {
+
+	public DiscreteValueSetModel(List<StringModel> values, Reporter log) {
+		super(values, log);
+	}
+
+	public DiscreteValueSetModel(Reporter log) {
+		super(Arrays.asList(new StringModel("value", log)), log);
+	}
+
+	@Override
+	public void remove(StringModel value) {
+		if (getSize() == 1) {
+			log.log(Level.WARNING,
+					"remove not allowed, as value set always must contain at least 1 value");
+			return;
+		}
+		super.remove(value);
+	}
+
+	/**
+	 * 
+	 * @return the {@link DiscreteValueSet} as set up by this model
+	 */
+	@Override
+	public DiscreteValueSet getCurrentValue() {
+		Collection<DiscreteValue> dvals = new LinkedList<>();
+		for (int n = 0; n < getSize(); n++) {
+			dvals.add(new DiscreteValue(get(n).getValue()));
+		}
+		return new DiscreteValueSet(dvals);
+	}
+
+	@Override
+	public BasicModel first() {
+		return get(0);
+	}
+
+	@Override
+	public ListModel<StringModel> getList() {
+		return this;
+	}
+
+	@Override
+	public void setCurrentValue(ValueSet obj) throws IllegalArgumentException {
+		if (!(obj instanceof DiscreteValueSet))
+			throw new IllegalArgumentException(
+					"Argument must be a DiscreteValueSet but got " + obj);
+		DiscreteValueSet valset = (DiscreteValueSet) obj;
+		List<StringModel> oldvals = new LinkedList<>();
+		for (int n = 0; n < getSize(); n++) {
+			oldvals.add(get(n));
+		}
+
+		// first add the new vals because minimum size.
+		for (DiscreteValue val : valset.getValues()) {
+			add(new StringModel(val.getValue(), log));
+		}
+		for (StringModel old : oldvals) {
+			remove(old);
+		}
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/DomainModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/DomainModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/DomainModel.java	(revision 49)
@@ -0,0 +1,153 @@
+package geniusweb.domaineditor.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.domaineditor.ProfileEditor;
+import geniusweb.issuevalue.Domain;
+import geniusweb.issuevalue.ValueSet;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.DefaultMapModel;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.Model;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.model.TypedModel;
+import tudelft.utilities.mvc.model.events.Changed;
+import tudelft.utilities.mvc.model.events.Event;
+
+/**
+ * Contains a mutable {@link Domain}. Listeners are notified about any changes
+ * and can act accordingly. Notifications contain WHAT changed: the name of the
+ * issue, or "" if the NAME changed of the domain. For internal use in the
+ * {@link ProfileEditor} and related
+ *
+ */
+public class DomainModel extends DefaultListenable<Event>
+		implements TypedModel<Domain> {
+	private static final ObjectMapper jackson = new ObjectMapper();
+	private final StringModel domainname;
+	private final MapModel<StringModel, ValueSetModel> issuesmodel;
+	private final Reporter log;
+
+	public DomainModel(StringModel name,
+			MapModel<StringModel, ValueSetModel> issues, Reporter log) {
+		if (issues.getMinimumSize() != 1)
+			throw new IllegalArgumentException(
+					"domain must have minimum size of at least 1 issue");
+		this.domainname = name;
+		this.issuesmodel = issues;
+		this.log = log;
+		DomainModel that = this;
+		domainname.addListener((e) -> notifyListeners(new Changed(this, e)));
+		// dont wrap issuemodel events into another Changed, it's already in one
+		issuesmodel.addListener((e) -> notifyListeners(e));
+	}
+
+	public DomainModel(Reporter log) {
+		this(new StringModel("noname", log),
+				new DefaultMapModel<StringModel, ValueSetModel>(
+						Collections.singletonMap(new StringModel("issue", log),
+								new DiscreteValueSetModel(log)),
+						log) {
+					@Override
+					public int getMinimumSize() {
+						return 1;
+					}
+
+					@Override
+					public String getColumnName(int n) {
+						return n == 0 ? "issue" : "value";
+					}
+
+					@Override
+					public ValueSetModel create(StringModel key) {
+						throw new UnsupportedOperationException();
+					}
+
+				}, log);
+	}
+
+	/**
+	 * Create the domain from a file.
+	 * 
+	 * @param file the file containing the domain
+	 * @throws Exception if problem with the file
+	 */
+	public static DomainModel create(File file, Reporter log)
+			throws JsonParseException, JsonMappingException, IOException {
+		Domain domain = jackson.readValue(file, Domain.class);
+		// FIXME
+		return new DomainModel(new StringModel(domain.getName(), log), null,
+				log);
+	}
+
+	/**
+	 * 
+	 * @return the model containing the domain name.
+	 */
+	public StringModel getNameModel() {
+		return domainname;
+	}
+
+	/**
+	 * 
+	 * @return the model containing the issues-values map
+	 */
+	public MapModel<StringModel, ValueSetModel> getIssuesModel() {
+		return issuesmodel;
+	}
+
+	/**
+	 * 
+	 * @return the {@link Domain} contained in this model.
+	 */
+	@Override
+	public Domain getCurrentValue() throws IllegalStateException {
+		Map<String, ValueSet> issues = new HashMap<>();
+		for (int n = 0; n < issuesmodel.getKeys().getSize(); n++) {
+			StringModel key = issuesmodel.getKeys().get(n);
+			issues.put(key.getValue(),
+					issuesmodel.getValue(key).getCurrentValue());
+		}
+
+		return new Domain(domainname.getValue(), issues);
+	}
+
+	/**
+	 * Set new {@link Domain}
+	 * 
+	 * @param obj the new {@link Domain}. This assumes the old domain can be
+	 *            completely deleted and replaced with this new one. New
+	 *            {@link Model}s are created where needed.
+	 */
+	@Override
+	public void setCurrentValue(Domain dom) throws IllegalArgumentException {
+		domainname.setValue(dom.getName());
+
+		// collect old issues
+		List<StringModel> oldissues = new LinkedList<>();
+		for (int n = 0; n < issuesmodel.getKeys().getSize(); n++)
+			oldissues.add(issuesmodel.getKeys().get(n));
+
+		// add new ones first (minimum size)
+		for (String iss : dom.getIssues()) {
+			ValueSetModel valsetmodel = ValueSetModelType.createModel(
+					ValueSetModelType.fromModel(dom.getValues(iss)), log);
+			valsetmodel.setCurrentValue(dom.getValues(iss));
+			issuesmodel.put(new StringModel(iss, log), valsetmodel);
+		}
+		// remove the old issues
+		for (StringModel iss : oldissues)
+			issuesmodel.remove(iss);
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/NumberValueSetModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/NumberValueSetModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/NumberValueSetModel.java	(revision 49)
@@ -0,0 +1,170 @@
+package geniusweb.domaineditor.model;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import geniusweb.issuevalue.NumberValueSet;
+import geniusweb.issuevalue.ValueSet;
+import tudelft.utilities.immutablelist.Range;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.BasicModel;
+import tudelft.utilities.mvc.model.ListModel;
+import tudelft.utilities.mvc.model.NumberModel;
+import tudelft.utilities.mvc.model.events.Changed;
+import tudelft.utilities.mvc.model.events.Event;
+
+/**
+ * Model for a {@link NumberValueSet}
+ *
+ */
+public class NumberValueSetModel extends DefaultListenable<Event>
+		implements ValueSetModel {
+
+	private final NumberModel low, high, step;
+	protected final Reporter log;
+
+	public NumberValueSetModel(NumberModel lowv, NumberModel highv,
+			NumberModel stepv, Reporter log) {
+		this.low = lowv;
+		this.high = highv;
+		this.step = stepv;
+		this.log = log;
+
+		check();
+
+		// 'this' refers to surrounding class inside lambda.
+		low.addListener((e) -> check());
+		high.addListener((e) -> check());
+		step.addListener((e) -> check());
+	}
+
+	private void check() throws IllegalStateException {
+		if (low.getValue().compareTo(high.getValue()) > 0)
+			throw new IllegalStateException("low must be <= high");
+		if (step.getValue().compareTo(BigDecimal.ZERO) <= 0)
+			throw new IllegalStateException("step must be >0");
+		notifyListeners(new Changed(this, null));
+	}
+
+	/*
+	 * Default, bit arbitrary values.
+	 */
+	public NumberValueSetModel(Reporter log) {
+		this(new NumberModel(BigDecimal.ZERO, log),
+				new NumberModel(BigDecimal.TEN, log),
+				new NumberModel(BigDecimal.ONE, log), log);
+	}
+
+	@Override
+	public String toString() {
+		return "(" + low + high + step + ")";
+	}
+
+	public NumberModel getLow() {
+		return low;
+	}
+
+	public NumberModel getHigh() {
+		return high;
+
+	}
+
+	public NumberModel getStep() {
+		return step;
+	}
+
+	@Override
+	public BasicModel first() {
+		return low;
+	}
+
+	@Override
+	public ListModel getList() {
+		/**
+		 * Return a ListModel backed up by the original set. It contains the
+		 * possible values in the range.
+		 */
+		return new MyListModel(this);
+	}
+
+	@Override
+	public NumberValueSet getCurrentValue() throws IllegalStateException {
+		return new NumberValueSet(
+				new Range(low.getValue(), high.getValue(), step.getValue()));
+	}
+
+	@Override
+	public void setCurrentValue(ValueSet obj) throws IllegalArgumentException {
+		if (!(obj instanceof NumberValueSet))
+			throw new IllegalArgumentException(
+					"Argument must be a NumberValueSet but got " + obj);
+		NumberValueSet nv = (NumberValueSet) obj;
+		// order of change is important, avoiding illegal ranges:
+		// if low must be increased, change high first.
+		// if high must be decreased, change low first.
+		// otherwise the change order is irrelevant.
+		if (nv.getRange().getLow().compareTo(low.getValue()) > 0) {
+			high.setValue(nv.getRange().getHigh());
+			low.setValue(nv.getRange().getLow());
+		} else {
+			low.setValue(nv.getRange().getLow());
+			high.setValue(nv.getRange().getHigh());
+		}
+		step.setValue(nv.getRange().getStep());
+	}
+
+}
+
+/**
+ * A ListModel view of this object. Editing is not supported.
+ *
+ */
+class MyListModel extends DefaultListenable<Event>
+		implements ListModel<NumberModel> {
+
+	private NumberValueSetModel numvalset;
+	/**
+	 * A "cache" Map with the actual values from the range. Although
+	 * NumberModels, they really should not be edited. This map ensures we
+	 * return the SAME NumberModel every time a value from the range is
+	 * selected.
+	 */
+	private final transient Map<BigDecimal, NumberModel> itemsCache = new HashMap<>();
+
+	public MyListModel(NumberValueSetModel valset) {
+		this.numvalset = valset;
+		valset.addListener((e) -> notifyListeners(e));
+	}
+
+	@Override
+	public NumberModel get(int n) {
+		BigDecimal val = numvalset.getCurrentValue().getRange().get(n);
+		if (!itemsCache.containsKey(val))
+			itemsCache.put(val, new NumberModel(val, numvalset.log));
+		return itemsCache.get(val);
+	}
+
+	@Override
+	public int getSize() {
+		return numvalset.getCurrentValue().getRange().size().intValue();
+	}
+
+	@Override
+	public void remove(NumberModel value) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void add(NumberModel value) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public boolean contains(Object o) {
+		return o instanceof NumberModel && numvalset.getCurrentValue()
+				.getRange().contains(((NumberModel) o).getValue());
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/ValueSetModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/ValueSetModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/ValueSetModel.java	(revision 49)
@@ -0,0 +1,27 @@
+package geniusweb.domaineditor.model;
+
+import geniusweb.issuevalue.ValueSet;
+import tudelft.utilities.mvc.model.BasicModel;
+import tudelft.utilities.mvc.model.ListModel;
+import tudelft.utilities.mvc.model.TypedModel;
+
+/**
+ * Contains a {@link ValueSet}. See the DiscreteValueSetModel- and
+ * {@link NumberValueSetModel}
+ *
+ */
+public interface ValueSetModel extends TypedModel<ValueSet> {
+	/**
+	 * 
+	 * @return first value in the model
+	 */
+	BasicModel first();
+
+	/**
+	 * 
+	 * @return {@link ListModel} with the available values. This ListModel may
+	 *         not support edit actions.
+	 */
+	public ListModel<? extends BasicModel> getList();
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/ValueSetModelType.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/ValueSetModelType.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/ValueSetModelType.java	(revision 49)
@@ -0,0 +1,71 @@
+package geniusweb.domaineditor.model;
+
+import geniusweb.issuevalue.DiscreteValueSet;
+import geniusweb.issuevalue.NumberValueSet;
+import geniusweb.issuevalue.ValueSet;
+import tudelft.utilities.logging.Reporter;
+
+/**
+ * Types of {@link ValueSetModel} and Model factory
+ *
+ */
+public enum ValueSetModelType {
+	DISCRETE(DiscreteValueSetModel.class), NUMBER(NumberValueSetModel.class);
+
+	private Class<? extends ValueSetModel> modelclass;
+
+	/**
+	 * 
+	 * @param clas the model class matching with this type.
+	 */
+	ValueSetModelType(Class<? extends ValueSetModel> clas) {
+		this.modelclass = clas;
+	}
+
+	/**
+	 * 
+	 * @param valueset the {@link ValueSet} to get type of
+	 * @return the type
+	 */
+	public static ValueSetModelType fromModel(ValueSet valueset) {
+		if (valueset instanceof DiscreteValueSet)
+			return DISCRETE;
+		if (valueset instanceof NumberValueSet)
+			return NUMBER;
+		throw new IllegalArgumentException(
+				"valueset of Unknown class " + valueset);
+	}
+
+	/**
+	 * Find the Type for the given model.
+	 * 
+	 * @param model {@link ValueSetModel}
+	 * @return {@link ValueSetModelType}
+	 */
+	public static ValueSetModelType fromModel(ValueSetModel model) {
+		for (ValueSetModelType type : ValueSetModelType.values()) {
+			if (model.getClass().equals(type.modelclass))
+				return type;
+		}
+		throw new IllegalArgumentException("Model of Unknown class " + model);
+	}
+
+	public static ValueSetModel createModel(ValueSetModelType type,
+			Reporter log) {
+		switch (type) {
+		case DISCRETE:
+			return new DiscreteValueSetModel(log);
+		case NUMBER:
+			return new NumberValueSetModel(log);
+		}
+		return null; // unreachable code
+	}
+
+	/**
+	 * 
+	 * @return the other type
+	 */
+	public ValueSetModelType otherType() {
+		return this == DISCRETE ? NUMBER : DISCRETE;
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/DiscreteValueSetUtilitiesModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/DiscreteValueSetUtilitiesModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/DiscreteValueSetUtilitiesModel.java	(revision 49)
@@ -0,0 +1,115 @@
+package geniusweb.domaineditor.model.profile;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import geniusweb.domaineditor.model.DiscreteValueSetModel;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.profile.utilityspace.DiscreteValueSetUtilities;
+import geniusweb.profile.utilityspace.ValueSetUtilities;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.ListModel;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.NumberModel;
+import tudelft.utilities.mvc.model.RestrictedNumberModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.model.events.Event;
+import tudelft.utilities.mvc.panels.PopupReporter;
+
+/**
+ * 
+ * Contains info for a {@link DiscreteValueSetUtilities} as a map. The keys of
+ * the map are the issuevalues in the {@link DiscreteValueSetModel}, the values
+ * are the utilities stored in this model.
+ *
+ */
+public class DiscreteValueSetUtilitiesModel extends DefaultListenable<Event>
+		implements MapModel<StringModel, RestrictedNumberModel>,
+		ValueSetUtilitiesModel {
+	private final ListModel<StringModel> values;
+	private final Map<StringModel, RestrictedNumberModel> utilities = new HashMap<>();
+	private final Reporter log;
+	private static final BigDecimal DEFAULT = new BigDecimal("0.5");
+	// this reporter in theory is never used.
+	// it's connected to values that never change
+	private final static Reporter dummylog = new PopupReporter(null);
+	private final static NumberModel LOW = new NumberModel(BigDecimal.ZERO,
+			dummylog);
+	private final static NumberModel HIGH = new NumberModel(BigDecimal.ONE,
+			dummylog);
+
+	public DiscreteValueSetUtilitiesModel(DiscreteValueSetModel values,
+			Reporter log) {
+		this.values = values.getList();
+		this.log = log;
+	}
+
+	@Override
+	public RestrictedNumberModel getValue(StringModel key) {
+		if (!utilities.containsKey(key)) {
+			utilities.put(key,
+					new RestrictedNumberModel(DEFAULT, LOW, HIGH, log));
+		}
+		return utilities.get(key);
+	}
+
+	@Override
+	public void put(StringModel key, RestrictedNumberModel val) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void remove(StringModel key) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public ListModel<StringModel> getKeys() {
+		return values;
+	}
+
+	@Override
+	public int getMinimumSize() {
+		return 1;
+	}
+
+	@Override
+	public String getColumnName(int n) {
+		return n == 0 ? "value" : "utility";
+	}
+
+	@Override
+	public DiscreteValueSetUtilities getCurrentValue()
+			throws IllegalStateException {
+		Map<DiscreteValue, BigDecimal> map = new HashMap<>();
+		for (int n = 0; n < values.getSize(); n++) {
+			StringModel val = values.get(n);
+			map.put(new DiscreteValue(val.getValue()),
+					getValue(val).getValue());
+		}
+
+		return new DiscreteValueSetUtilities(map);
+	}
+
+	@Override
+	public void setCurrentValue(ValueSetUtilities obj)
+			throws IllegalArgumentException {
+		DiscreteValueSetUtilities vutils = (DiscreteValueSetUtilities) obj;
+		for (int n = 0; n < values.getSize(); n++) {
+			StringModel val = values.get(n);
+			// FIXME this silently uses util 0 if value not in bid. Maybe warn?
+			BigDecimal util = vutils
+					.getUtility(new DiscreteValue(val.getValue()));
+			getValue(val).setValue(util);
+		}
+
+	}
+
+	@Override
+	public RestrictedNumberModel create(StringModel key) {
+		throw new UnsupportedOperationException();
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/LinearAdditiveUtilitySpaceModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/LinearAdditiveUtilitySpaceModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/LinearAdditiveUtilitySpaceModel.java	(revision 49)
@@ -0,0 +1,261 @@
+package geniusweb.domaineditor.model.profile;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import geniusweb.domaineditor.model.BidModel;
+import geniusweb.domaineditor.model.DiscreteValueSetModel;
+import geniusweb.domaineditor.model.DomainModel;
+import geniusweb.domaineditor.model.NumberValueSetModel;
+import geniusweb.domaineditor.model.ValueSetModel;
+import geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace;
+import geniusweb.profile.utilityspace.ValueSetUtilities;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.ListModel;
+import tudelft.utilities.mvc.model.MapFromKeys;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.NumberModel;
+import tudelft.utilities.mvc.model.RestrictedNumberModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.model.TypedModel;
+import tudelft.utilities.mvc.model.events.Event;
+import tudelft.utilities.mvc.panels.PopupReporter;
+
+/**
+ * Model containing a {@link LinearAdditiveUtilitySpace}
+ */
+public class LinearAdditiveUtilitySpaceModel extends DefaultListenable<Event>
+		implements ProfileModel, TypedModel<LinearAdditiveUtilitySpace> {
+	private final StringModel name;
+	/**
+	 * the key is the issue, the value is the valuesetutilities for this issue.
+	 * Should be immutable so do not return direct access to this field.
+	 */
+	private final MapModel<StringModel, ValueSetUtilitiesModel> issueUtilities;
+
+	/**
+	 * The key is the issue, the value is the weight of the utilities for that
+	 * issue (utility as returned from the ValueSetUtilities for that issue).
+	 */
+	private final MapModel<StringModel, RestrictedNumberModel> issueWeights;
+
+	private final DomainModel domain;
+
+	private final BidModel reservationBid;
+	private Reporter log;
+
+	/**
+	 * The
+	 * 
+	 * @param name
+	 * @param issueUtilities a map of issue-values. Issues are
+	 *                       {@link StringModel}.
+	 * @param weights        the issue weights. RestrictedNumberModel with
+	 *                       minimum 0 and max 1. The set of keys (issue
+	 *                       {@link StringModel}) must equal the issueUtilities
+	 *                       keyMap
+	 * @param domain         the {@link DomainModel}. Issues in the domain must
+	 *                       equal to issueUtities keys.
+	 * @param reservationBid the {#link BidModel} holding the reservation bid
+	 * @param log            the {@link Reporter}
+	 */
+	public LinearAdditiveUtilitySpaceModel(StringModel name,
+			MapModel<StringModel, ValueSetUtilitiesModel> issueUtilities,
+			MapModel<StringModel, RestrictedNumberModel> weights,
+			DomainModel domain, BidModel reservationBid, Reporter log) {
+		if (!domain.getIssuesModel().getKeys().equals(issueUtilities.getKeys()))
+			throw new IllegalArgumentException(
+					"issues in domain and isseuUtilities are not equal");
+		if (!domain.getIssuesModel().getKeys().equals(weights.getKeys()))
+			throw new IllegalArgumentException(
+					"issues in domain and weight map are not equal");
+		this.name = name;
+		this.issueUtilities = issueUtilities;
+		this.issueWeights = weights;
+		this.domain = domain;
+		this.reservationBid = reservationBid;
+		this.log = log;
+	}
+
+	protected static final BigDecimal N05 = new BigDecimal("0.5");
+	// dummylog is for events that should never happen.
+	private static Reporter dummylog = new PopupReporter(null);
+	// we should never allow editing of these constants.
+	protected static final NumberModel CONSTANT0 = new NumberModel(
+			BigDecimal.ZERO, dummylog);
+	protected static final NumberModel CONSTANT1 = new NumberModel(
+			BigDecimal.ONE, dummylog);
+
+	public LinearAdditiveUtilitySpaceModel(DomainModel domain,
+			final Reporter log) {
+		this(new StringModel("domainname", log), createUtilsMap(domain, log),
+				createWeightMap(domain, log), domain,
+				new BidModel(domain.getIssuesModel(), log), log);
+	}
+
+	/**
+	 * creates a initial weight map for domain
+	 * 
+	 * @param domain2
+	 * @return MapModel with issue-weight pairs. Map keys are issues from the
+	 *         domain.
+	 */
+	private static MapModel<StringModel, RestrictedNumberModel> createWeightMap(
+			final DomainModel domain2, final Reporter log) {
+		return new MapFromKeys<StringModel, RestrictedNumberModel>(
+				domain2.getIssuesModel().getKeys(), log, true) {
+
+			@Override
+			public RestrictedNumberModel create(StringModel key) {
+				return new RestrictedNumberModel(N05, CONSTANT0, CONSTANT1,
+						log);
+			}
+
+			@Override
+			public String getColumnName(int n) {
+				return n == 0 ? "issue" : "weight";
+			}
+
+		};
+	}
+
+	private static MapModel<StringModel, ValueSetUtilitiesModel> createUtilsMap(
+			final DomainModel domain2, final Reporter log) {
+		// do not retain old values, issues may be removed and replaced with
+		// different type
+		return new MapFromKeys<StringModel, ValueSetUtilitiesModel>(
+				domain2.getIssuesModel().getKeys(), log, false) {
+			@Override
+			public ValueSetUtilitiesModel create(StringModel key) {
+				ValueSetModel val = domain2.getIssuesModel().getValue(key);
+				if (val instanceof DiscreteValueSetModel)
+					return new DiscreteValueSetUtilitiesModel(
+							(DiscreteValueSetModel) val, log);
+				if (val instanceof NumberValueSetModel)
+					return new NumberValueSetUtilitiesModel(
+							(NumberValueSetModel) val, log);
+				throw new RuntimeException(
+						"Unsupported type " + val + "for key" + key);
+			}
+
+			@Override
+			public String getColumnName(int n) {
+				return n == 0 ? "value" : "utility";
+			}
+
+		};
+	}
+
+	/**
+	 * 
+	 * @return the {@link DomainModel}
+	 */
+	public DomainModel getDomain() {
+		return domain;
+	}
+
+	/**
+	 * 
+	 * @return {@link StringModel} containing the domain name
+	 */
+	public StringModel getName() {
+		return name;
+	}
+
+	/**
+	 * 
+	 * @return {@link BidModel} containing the reservation bid
+	 */
+	public BidModel getReservationBid() {
+		return reservationBid;
+	}
+
+	/**
+	 * @return the weights map, but all weights are NOT NORMALIZED.
+	 */
+	public MapModel<StringModel, RestrictedNumberModel> getWeights() {
+		return issueWeights;
+	}
+
+	/**
+	 * 
+	 * @return the issue utilities map
+	 */
+	public MapModel<StringModel, ValueSetUtilitiesModel> getIssueUtilities() {
+		return issueUtilities;
+	}
+
+	@Override
+	public LinearAdditiveUtilitySpace getCurrentValue()
+			throws IllegalStateException {
+		return new LinearAdditiveUtilitySpace(domain.getCurrentValue(),
+				name.getValue(), getUtilitiesMap(), getNormalizedWeightMap(),
+				reservationBid.getCurrentValue());
+	}
+
+	/**
+	 * 
+	 * @return a Utilities map as contained in the current settings
+	 */
+	private Map<String, ValueSetUtilities> getUtilitiesMap() {
+		Map<String, ValueSetUtilities> map = new HashMap<>();
+		for (int n = 0; n < issueUtilities.getKeys().getSize(); n++) {
+			StringModel issuem = issueUtilities.getKeys().get(n);
+			map.put(issuem.getValue(),
+					issueUtilities.getValue(issuem).getCurrentValue());
+		}
+		return map;
+	}
+
+	@Override
+	public void setCurrentValue(LinearAdditiveUtilitySpace obj)
+			throws IllegalArgumentException {
+		LinearAdditiveUtilitySpace space = obj;
+		name.setValue(space.getName());
+		domain.setCurrentValue(space.getDomain());
+		reservationBid.setCurrentValue(space.getReservationBid());
+
+		ListModel<StringModel> issuesm = domain.getIssuesModel().getKeys();
+		for (int n = 0; n < issuesm.getSize(); n++) {
+			StringModel issuem = issuesm.get(n);
+			String issue = issuem.getValue();
+			issueWeights.getValue(issuem).setValue(space.getWeight(issue));
+			issueUtilities.getValue(issuem)
+					.setCurrentValue(space.getUtilities().get(issue));
+		}
+
+	}
+
+	/**
+	 * 
+	 * @return normalized weight map
+	 */
+	protected Map<String, BigDecimal> getNormalizedWeightMap() {
+		Map<String, BigDecimal> weights = new HashMap<>();
+		for (int n = 0; n < issueWeights.getKeys().getSize(); n++) {
+			StringModel key = issueWeights.getKeys().get(n);
+			weights.put(key.getValue(), issueWeights.getValue(key).getValue());
+		}
+
+		BigDecimal sum = weights.values().stream().reduce(BigDecimal.ZERO,
+				BigDecimal::add);
+		// weights1 may still contain rounding errors
+		Map<String, BigDecimal> normap = weights.entrySet().stream()
+				.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()
+						.divide(sum, 6, RoundingMode.HALF_UP)));
+		BigDecimal err = normap.values().stream()
+				.reduce(BigDecimal.ZERO, BigDecimal::add)
+				.subtract(BigDecimal.ONE);
+		// just subtract err from the biggest value
+		String maxkey = Collections
+				.max(normap.entrySet(), Map.Entry.comparingByValue()).getKey();
+		normap.put(maxkey, normap.get(maxkey).subtract(err));
+		return normap;
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/NumberValueSetUtilitiesModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/NumberValueSetUtilitiesModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/NumberValueSetUtilitiesModel.java	(revision 49)
@@ -0,0 +1,97 @@
+package geniusweb.domaineditor.model.profile;
+
+import java.math.BigDecimal;
+
+import geniusweb.domaineditor.model.NumberValueSetModel;
+import geniusweb.profile.utilityspace.NumberValueSetUtilities;
+import geniusweb.profile.utilityspace.ValueSetUtilities;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.NumberModel;
+import tudelft.utilities.mvc.model.RestrictedNumberModel;
+import tudelft.utilities.mvc.model.events.Event;
+import tudelft.utilities.mvc.panels.PopupReporter;
+
+/**
+ * Contains info for a {@link NumberValueSetUtilities}
+ *
+ */
+public class NumberValueSetUtilitiesModel extends DefaultListenable<Event>
+		implements ValueSetUtilitiesModel {
+
+	private static final BigDecimal DEFAULT = new BigDecimal("0.5");
+	// this reporter in theory is never used.
+	// it's connected to values that never change
+	private final static Reporter dummylog = new PopupReporter(null);
+	private final static NumberModel LOW = new NumberModel(BigDecimal.ZERO,
+			dummylog);
+	private final static NumberModel HIGH = new NumberModel(BigDecimal.ONE,
+			dummylog);
+	private final NumberModel lowValue;
+	private final RestrictedNumberModel lowUtility;
+	private final NumberModel highValue;
+	private final RestrictedNumberModel highUtility;
+
+	/**
+	 * 
+	 * @param lowValue
+	 * @param lowUtility  a {@link RestrictedNumberModel} with min=0, max=100
+	 * @param highValue
+	 * @param highUtility a {@link RestrictedNumberModel} with min=0, max=100
+	 */
+	NumberValueSetUtilitiesModel(NumberModel lowValue,
+			RestrictedNumberModel lowUtility, NumberModel highValue,
+			RestrictedNumberModel highUtility) {
+		this.lowValue = lowValue;
+		this.lowUtility = lowUtility;
+		this.highValue = highValue;
+		this.highUtility = highUtility;
+	}
+
+	NumberValueSetUtilitiesModel(NumberValueSetModel valuesmodel,
+			Reporter log) {
+		this(valuesmodel.getLow(),
+				new RestrictedNumberModel(DEFAULT, LOW, HIGH, log),
+				valuesmodel.getHigh(),
+				new RestrictedNumberModel(DEFAULT, LOW, HIGH, log));
+	}
+
+	public NumberModel getLowValue() {
+		return lowValue;
+	}
+
+	public RestrictedNumberModel getLowUtility() {
+		return lowUtility;
+	}
+
+	public NumberModel getHighValue() {
+		return highValue;
+	}
+
+	public RestrictedNumberModel getHighUtility() {
+		return highUtility;
+	}
+
+	@Override
+	public NumberValueSetUtilities getCurrentValue()
+			throws IllegalStateException {
+		return new NumberValueSetUtilities(lowValue.getValue(),
+				lowUtility.getValue(), highValue.getValue(),
+				highUtility.getValue());
+	}
+
+	@Override
+	public void setCurrentValue(ValueSetUtilities obj)
+			throws IllegalArgumentException {
+		if (!(obj instanceof NumberValueSetUtilities))
+			throw new IllegalArgumentException(
+					"Expected instance of NumberValueSetUtilities but got "
+							+ obj);
+		NumberValueSetUtilities utils = (NumberValueSetUtilities) obj;
+		// FIXME this may fail if new lowvalue > old highvalue
+		lowValue.setValue(utils.getLowValue());
+		lowUtility.setValue(utils.getLowUtility());
+		highValue.setValue(utils.getHighValue());
+		highUtility.setValue(utils.getHighUtility());
+	}
+};
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/ProfileModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/ProfileModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/ProfileModel.java	(revision 49)
@@ -0,0 +1,12 @@
+package geniusweb.domaineditor.model.profile;
+
+import geniusweb.profile.Profile;
+import tudelft.utilities.mvc.model.Model;
+
+/**
+ * ProfileModel for a {@link Profile}
+ *
+ */
+public interface ProfileModel extends Model {
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/ValueSetUtilitiesModel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/ValueSetUtilitiesModel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/model/profile/ValueSetUtilitiesModel.java	(revision 49)
@@ -0,0 +1,12 @@
+package geniusweb.domaineditor.model.profile;
+
+import geniusweb.profile.utilityspace.ValueSetUtilities;
+import tudelft.utilities.mvc.model.TypedModel;
+
+/**
+ * Contains editable {@link ValueSetUtilities}
+ *
+ */
+public interface ValueSetUtilitiesModel extends TypedModel<ValueSetUtilities> {
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/panels/BidEditorPanel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/panels/BidEditorPanel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/panels/BidEditorPanel.java	(revision 49)
@@ -0,0 +1,182 @@
+package geniusweb.domaineditor.panels;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.util.EventObject;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.CellEditorListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableModel;
+
+import geniusweb.domaineditor.model.BidModel;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.Model;
+import tudelft.utilities.mvc.model.SelectionModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.PanelFactory;
+
+/**
+ * Panel ot edit Bids. This is not a standard MapModelPanel because the issues
+ * and values are not directly editable; rather the user can only pick existing
+ * values.
+ *
+ */
+public class BidEditorPanel extends JPanel {
+
+	public BidEditorPanel(BidModel model) {
+		setLayout(new BorderLayout());
+		MyTableModel jtablemodel = new MyTableModel(model);
+		JTable table = new JTable(jtablemodel);
+		table.setDefaultRenderer(Object.class, new TableCellRenderer() {
+
+			@Override
+			public Component getTableCellRendererComponent(JTable table,
+					Object value, boolean isSelected, boolean hasFocus, int row,
+					int column) {
+				return (Component) value;
+			}
+		});
+		table.setDefaultEditor(Object.class, new TableCellEditor() {
+			private List<CellEditorListener> listeners = new LinkedList<>();
+
+			@Override
+			public Object getCellEditorValue() {
+				return null;
+			}
+
+			@Override
+			public boolean isCellEditable(EventObject anEvent) {
+				return true;
+			}
+
+			@Override
+			public boolean shouldSelectCell(EventObject anEvent) {
+				return true;
+			}
+
+			@Override
+			public boolean stopCellEditing() {
+				for (CellEditorListener l : listeners)
+					l.editingStopped(null);
+				return true;
+			}
+
+			@Override
+			public void cancelCellEditing() {
+				for (CellEditorListener l : listeners)
+					l.editingStopped(null);
+			}
+
+			@Override
+			public void addCellEditorListener(CellEditorListener l) {
+				listeners.add(l);
+			}
+
+			@Override
+			public void removeCellEditorListener(CellEditorListener l) {
+				listeners.remove(l);
+			}
+
+			@Override
+			public Component getTableCellEditorComponent(JTable table,
+					Object value, boolean isSelected, int row, int column) {
+				// only column 2 is editable so this must be a combo selector
+				return (Component) value;
+			}
+
+		});
+		table.setRowSelectionAllowed(true);
+		table.setCellSelectionEnabled(false);
+		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
+		add(new JScrollPane(table), BorderLayout.CENTER);
+	}
+}
+
+/**
+ * The list is actually shown in a {@link JTable}. This maps our TableModel into
+ * something JTable can digest.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ */
+class MyTableModel<K extends Model, V extends Model> implements TableModel {
+	private final PanelFactory panelfactory;
+
+	private final MapModel<StringModel, SelectionModel> issuevalues;
+	private List<TableModelListener> listeners = new LinkedList<>();
+
+	public MyTableModel(MapModel<StringModel, SelectionModel> issuevalues,
+			PanelFactory panelfactory) {
+		this.panelfactory = panelfactory;
+		this.issuevalues = issuevalues;
+		issuevalues.addListener((data) -> notifyListeners());
+	}
+
+	public MyTableModel(MapModel<StringModel, SelectionModel> issuevalues) {
+		this(issuevalues, new PanelFactory());
+	}
+
+	@Override
+	public int getRowCount() {
+		return issuevalues.getKeys().getSize();
+	}
+
+	@Override
+	public int getColumnCount() {
+		return 2;
+	}
+
+	@Override
+	public String getColumnName(int columnIndex) {
+		return columnIndex == 0 ? "issue" : "value";
+	}
+
+	@Override
+	public Class<?> getColumnClass(int columnIndex) {
+		return Component.class;
+	}
+
+	@Override
+	public boolean isCellEditable(int rowIndex, int columnIndex) {
+		return columnIndex == 1; // only values can be edited
+	}
+
+	@Override
+	public Object getValueAt(int rowIndex, int columnIndex) {
+		StringModel key = issuevalues.getKeys().get(rowIndex);
+		return panelfactory
+				.create(columnIndex == 0 ? key : issuevalues.getValue(key));
+	}
+
+	@Override
+	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+	}
+
+	@Override
+	public void addTableModelListener(TableModelListener l) {
+		listeners.add(l);
+	}
+
+	@Override
+	public void removeTableModelListener(TableModelListener l) {
+		listeners.remove(l);
+
+	}
+
+	private void notifyListeners() {
+		for (TableModelListener l : listeners) {
+			l.tableChanged(new TableModelEvent(this));
+		}
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/panels/DiscreteValueSetPanel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/panels/DiscreteValueSetPanel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/panels/DiscreteValueSetPanel.java	(revision 49)
@@ -0,0 +1,33 @@
+package geniusweb.domaineditor.panels;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JPanel;
+
+import geniusweb.domaineditor.model.DiscreteValueSetModel;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.EditableListViewPanel;
+
+/**
+ * Editor for DiscreteValueSet
+ */
+@SuppressWarnings("serial")
+public class DiscreteValueSetPanel extends JPanel {
+	private final DiscreteValueSetModel model;
+	private int n = 1;
+
+	@SuppressWarnings("unchecked")
+	public DiscreteValueSetPanel(StringModel issuenamemodel,
+			DiscreteValueSetModel model, final Reporter log) {
+		this.model = model;
+		setLayout(new BorderLayout());
+		add(new EditableListViewPanel(model.getList()) {
+			@Override
+			protected void addItem() {
+				model.add(new StringModel("value " + (n++), log));
+
+			}
+		}, BorderLayout.CENTER);
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/panels/DomainEditorPanel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/panels/DomainEditorPanel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/panels/DomainEditorPanel.java	(revision 49)
@@ -0,0 +1,94 @@
+package geniusweb.domaineditor.panels;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import geniusweb.domaineditor.model.DiscreteValueSetModel;
+import geniusweb.domaineditor.model.DomainModel;
+import geniusweb.domaineditor.model.NumberValueSetModel;
+import geniusweb.domaineditor.model.ValueSetModel;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.CustomMapEditor;
+import tudelft.utilities.mvc.panels.LabeledPanel;
+import tudelft.utilities.mvc.panels.StringPanel;
+
+/**
+ * The actual editor panel for domains Domains are issues and their possible
+ * values.
+ */
+@SuppressWarnings("serial")
+public class DomainEditorPanel extends JPanel {
+
+	/**
+	 * Panel with on the left a set of strings (issues). When user selects an
+	 * issue, an editor is opened for the valueset of that issue.
+	 * 
+	 * @param domainmodel the {@link DomainModel} containing the issue and
+	 *                    valuesets.
+	 * @param log         used when generating new issue values
+	 */
+	public DomainEditorPanel(final DomainModel domainmodel, Reporter log) {
+		setLayout(new BorderLayout());
+
+		add(new LabeledPanel("domain name",
+				new StringPanel(domainmodel.getNameModel())),
+				BorderLayout.NORTH);
+		add(new IssuesMapEditor(domainmodel.getIssuesModel(), log),
+				BorderLayout.CENTER);
+
+	}
+}
+
+/**
+ * CustomMapEditor with issues on the left and editor for selected issue on the
+ * right.
+ */
+@SuppressWarnings("serial")
+class IssuesMapEditor
+		extends CustomMapEditor<String, StringModel, ValueSetModel> {
+	private final ValueSetEditorFactory vsetfactory = new ValueSetEditorFactory();
+	private Reporter logger;
+	private int n = 1;
+
+	public IssuesMapEditor(MapModel<StringModel, ValueSetModel> model,
+			Reporter log) {
+		super(model, true);
+		this.logger = log;
+	}
+
+	@Override
+	public Component getEditor(StringModel key) {
+		if (key == null)
+			return null; // how can this be?
+		ValueSetModel valuesetmodel = getModel().getValue(key);
+		System.out.println("key selected:" + key);
+		System.out.println("model contains key:" + valuesetmodel);
+		return vsetfactory.create(key, valuesetmodel, logger);
+	}
+
+	@Override
+	public void addEntry() {
+		JPanel panel = new JPanel(new BorderLayout());
+		panel.add(new JLabel("Select issue type"), BorderLayout.NORTH);
+		String[] types = { "discrete", "number" };
+		JComboBox combo = new JComboBox<>(types);
+		panel.add(combo, BorderLayout.CENTER);
+		JOptionPane.showMessageDialog(this, panel);
+		StringModel issuename = new StringModel("issue " + (n++), logger);
+		ValueSetModel valuesetmodel;
+		if (combo.getSelectedItem().equals("discrete"))
+			valuesetmodel = new DiscreteValueSetModel(logger);
+		else
+			valuesetmodel = new NumberValueSetModel(logger);
+		getModel().put(issuename, valuesetmodel);
+
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/panels/NumberValueSetPanel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/panels/NumberValueSetPanel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/panels/NumberValueSetPanel.java	(revision 49)
@@ -0,0 +1,28 @@
+package geniusweb.domaineditor.panels;
+
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+
+import geniusweb.domaineditor.model.NumberValueSetModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.LabeledPanel;
+import tudelft.utilities.mvc.panels.NumberPanel;
+import tudelft.utilities.mvc.panels.StringPanel;
+
+/**
+ * Editor for DiscreteValueSet
+ */
+public class NumberValueSetPanel extends JPanel {
+	private final NumberValueSetModel model;
+
+	public NumberValueSetPanel(StringModel issuenamemodel,
+			NumberValueSetModel model) {
+		this.model = model;
+		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+		add(new LabeledPanel("values for issue ",
+				new StringPanel(issuenamemodel)));
+		add(new LabeledPanel("low :", new NumberPanel(model.getLow())));
+		add(new LabeledPanel("high:", new NumberPanel(model.getHigh())));
+		add(new LabeledPanel("step:", new NumberPanel(model.getStep())));
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/panels/ValueSetEditorFactory.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/panels/ValueSetEditorFactory.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/panels/ValueSetEditorFactory.java	(revision 49)
@@ -0,0 +1,49 @@
+package geniusweb.domaineditor.panels;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JPanel;
+
+import geniusweb.domaineditor.model.DiscreteValueSetModel;
+import geniusweb.domaineditor.model.NumberValueSetModel;
+import geniusweb.domaineditor.model.ValueSetModel;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.LabeledPanel;
+import tudelft.utilities.mvc.panels.StringPanel;
+
+/**
+ * Factory to create ValueSet editor
+ * 
+ */
+public class ValueSetEditorFactory {
+
+//	private JComboBox typeselector = new JComboBox(Type.values());
+
+	/**
+	 * 
+	 * @param namemodel a {@link StringModel} holding name of the issue
+	 * @param model     the {@link ValueSetModel} containing the issue values.
+	 * @return editor panel for this issue
+	 */
+	public JPanel create(StringModel namemodel, ValueSetModel model,
+			Reporter log) {
+		JPanel panel = new JPanel(new BorderLayout());
+		panel.add(new LabeledPanel("values for issue ",
+				new StringPanel(namemodel)), BorderLayout.NORTH);
+		panel.add(create1(namemodel, model, log), BorderLayout.CENTER);
+		return panel;
+	}
+
+	private JPanel create1(StringModel namemodel, ValueSetModel model,
+			Reporter log) {
+		if (model instanceof DiscreteValueSetModel)
+			return new DiscreteValueSetPanel(namemodel,
+					(DiscreteValueSetModel) model, log);
+		if (model instanceof NumberValueSetModel)
+			return new NumberValueSetPanel(namemodel,
+					(NumberValueSetModel) model);
+		throw new IllegalArgumentException("Unknown model type " + model);
+	}
+
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/DiscreteValueSetUtilitiesPanel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/DiscreteValueSetUtilitiesPanel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/DiscreteValueSetUtilitiesPanel.java	(revision 49)
@@ -0,0 +1,20 @@
+package geniusweb.domaineditor.panels.profile;
+
+import geniusweb.domaineditor.model.profile.DiscreteValueSetUtilitiesModel;
+import tudelft.utilities.mvc.model.RestrictedNumberModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.MapPanel;
+
+/**
+ * Editor for discrete value set utilities.
+ */
+@SuppressWarnings("serial")
+public class DiscreteValueSetUtilitiesPanel
+		extends MapPanel<StringModel, RestrictedNumberModel> {
+	private DiscreteValueSetUtilitiesModel model;
+
+	public DiscreteValueSetUtilitiesPanel(
+			DiscreteValueSetUtilitiesModel model) {
+		super(model);
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/NumberValueSetUtilitiesPanel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/NumberValueSetUtilitiesPanel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/NumberValueSetUtilitiesPanel.java	(revision 49)
@@ -0,0 +1,27 @@
+package geniusweb.domaineditor.panels.profile;
+
+import java.awt.GridLayout;
+
+import javax.swing.JPanel;
+
+import geniusweb.domaineditor.model.profile.NumberValueSetUtilitiesModel;
+import tudelft.utilities.mvc.panels.NumberPanel;
+import tudelft.utilities.mvc.panels.SliderPanel;
+
+/**
+ * View/Controller of the {@link NumberValueSetUtilitiesModel}. Allows the user
+ * to change utilities of the low and high point.
+ */
+@SuppressWarnings("serial")
+public class NumberValueSetUtilitiesPanel extends JPanel {
+	private final NumberValueSetUtilitiesModel model;
+
+	public NumberValueSetUtilitiesPanel(NumberValueSetUtilitiesModel model) {
+		this.model = model;
+		setLayout(new GridLayout(2, 2));
+		add(new NumberPanel(model.getLowValue()));
+		add(new SliderPanel(model.getLowUtility()));
+		add(new NumberPanel(model.getHighValue()));
+		add(new SliderPanel(model.getHighUtility()));
+	}
+}
Index: /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/ProfileEditorPanel.java
===================================================================
--- /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/ProfileEditorPanel.java	(revision 49)
+++ /domaineditor/src/main/java/geniusweb/domaineditor/panels/profile/ProfileEditorPanel.java	(revision 49)
@@ -0,0 +1,71 @@
+package geniusweb.domaineditor.panels.profile;
+
+import java.awt.Component;
+
+import javax.swing.JTabbedPane;
+
+import geniusweb.domaineditor.model.profile.DiscreteValueSetUtilitiesModel;
+import geniusweb.domaineditor.model.profile.LinearAdditiveUtilitySpaceModel;
+import geniusweb.domaineditor.model.profile.NumberValueSetUtilitiesModel;
+import geniusweb.domaineditor.model.profile.ValueSetUtilitiesModel;
+import geniusweb.domaineditor.panels.BidEditorPanel;
+import geniusweb.domaineditor.panels.DomainEditorPanel;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.CustomMapEditor;
+import tudelft.utilities.mvc.panels.MapPanel;
+
+/**
+ * Editor for entire {@link LinearAdditiveUtilitySpaceModel}
+ *
+ */
+public class ProfileEditorPanel extends JTabbedPane {
+
+	private LinearAdditiveUtilitySpaceModel linmodel;
+	private Reporter log;
+
+	public ProfileEditorPanel(LinearAdditiveUtilitySpaceModel lamodel,
+			Reporter log) {
+		this.linmodel = lamodel;
+		this.log = log;
+
+		addTab("Domain", new DomainEditorPanel(linmodel.getDomain(), log));
+		addTab("Reservation Bid",
+				new BidEditorPanel(linmodel.getReservationBid()));
+		addTab("Utilities", new MyUtilsEditor(linmodel.getIssueUtilities()));
+		addTab("Weights", new MapPanel<>(linmodel.getWeights()));
+	}
+
+}
+
+/**
+ * CustomMapEditor for the utilities. Pulled out as getEditor is basically a
+ * factory.
+ *
+ */
+class MyUtilsEditor
+		extends CustomMapEditor<String, StringModel, ValueSetUtilitiesModel> {
+
+	public MyUtilsEditor(
+			MapModel<StringModel, ValueSetUtilitiesModel> issueUtilities) {
+		super(issueUtilities, false);
+	}
+
+	@Override
+	public void addEntry() {
+	}
+
+	@Override
+	public Component getEditor(StringModel key) {
+		ValueSetUtilitiesModel value = getModel().getValue(key);
+		if (value instanceof DiscreteValueSetUtilitiesModel)
+			return new DiscreteValueSetUtilitiesPanel(
+					(DiscreteValueSetUtilitiesModel) value);
+		if (value instanceof NumberValueSetUtilitiesModel)
+			return new NumberValueSetUtilitiesPanel(
+					(NumberValueSetUtilitiesModel) value);
+		throw new RuntimeException("Unknown valueset encountered:" + value);
+	}
+
+}
Index: /domaineditor/src/test/java/geniusweb/domaineditor/BidModelPanelTest.java
===================================================================
--- /domaineditor/src/test/java/geniusweb/domaineditor/BidModelPanelTest.java	(revision 49)
+++ /domaineditor/src/test/java/geniusweb/domaineditor/BidModelPanelTest.java	(revision 49)
@@ -0,0 +1,84 @@
+package geniusweb.domaineditor;
+
+import java.awt.BorderLayout;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import org.junit.Test;
+
+import geniusweb.domaineditor.model.BidModel;
+import geniusweb.domaineditor.model.DiscreteValueSetModel;
+import geniusweb.domaineditor.model.DomainModel;
+import geniusweb.domaineditor.model.ValueSetModel;
+import geniusweb.domaineditor.panels.BidEditorPanel;
+import geniusweb.domaineditor.panels.DomainEditorPanel;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.DefaultMapModel;
+import tudelft.utilities.mvc.model.DefaultSelectionModel;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.SelectionModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.PopupReporter;
+
+public class BidModelPanelTest {
+
+	private int n = 1;
+
+	@Test
+	public void teste2e() throws InterruptedException {
+		JFrame frame = new JFrame();
+		Reporter log = new PopupReporter(frame);
+
+		JPanel panel = new JPanel(new BorderLayout());
+
+		StringModel redvalue = new StringModel("red", log);
+		StringModel greenvalue = new StringModel("green", log);
+		DiscreteValueSetModel issue1values = new DiscreteValueSetModel(
+				Arrays.asList(redvalue, greenvalue), log);
+
+		StringModel issue1 = new StringModel("issue", log);
+
+		SelectionModel issue1valuessel = new DefaultSelectionModel(
+				issue1values);
+		Map<StringModel, SelectionModel> a = Collections.singletonMap(issue1,
+				issue1valuessel);
+
+		MapModel<StringModel, ValueSetModel> issuevaluesmodel = new DefaultMapModel<StringModel, ValueSetModel>(
+				Collections.singletonMap(issue1, issue1values), log) {
+
+			@Override
+			public String getColumnName(int n) {
+				return n == 0 ? "issue" : "value";
+			}
+
+			@Override
+			public ValueSetModel create(StringModel key) {
+				throw new UnsupportedOperationException();
+			}
+
+			@Override
+			public int getMinimumSize() {
+				return 1;
+			}
+
+		};
+		DomainModel domain = new DomainModel(new StringModel("testdomain", log),
+				issuevaluesmodel, log);
+
+		panel.add(new DomainEditorPanel(domain, log), BorderLayout.WEST);
+		panel.add(
+				new BidEditorPanel(new BidModel(domain.getIssuesModel(), log)),
+				BorderLayout.CENTER);
+
+		frame.getContentPane().add(panel);
+		frame.pack();
+		frame.setVisible(true);
+		Thread.sleep(10000);
+		frame.setVisible(false);
+	}
+
+}
Index: /domaineditor/src/test/java/geniusweb/domaineditor/DomainEditorPanelTest.java
===================================================================
--- /domaineditor/src/test/java/geniusweb/domaineditor/DomainEditorPanelTest.java	(revision 49)
+++ /domaineditor/src/test/java/geniusweb/domaineditor/DomainEditorPanelTest.java	(revision 49)
@@ -0,0 +1,69 @@
+package geniusweb.domaineditor;
+
+import java.awt.BorderLayout;
+import java.util.Collections;
+
+import javax.swing.JFrame;
+
+import org.junit.Test;
+
+import geniusweb.domaineditor.model.DiscreteValueSetModel;
+import geniusweb.domaineditor.model.DomainModel;
+import geniusweb.domaineditor.model.ValueSetModel;
+import geniusweb.domaineditor.panels.DomainEditorPanel;
+import tudelft.utilities.listener.Listener;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.DefaultMapModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.model.events.Event;
+import tudelft.utilities.mvc.panels.PopupReporter;
+
+public class DomainEditorPanelTest {
+	private int n = 1;
+
+	@Test
+	public void GuiTest() throws InterruptedException {
+		JFrame f = new JFrame();
+		Reporter log = new PopupReporter(f);
+		f.setLayout(new BorderLayout());
+
+		StringModel namemodel = new StringModel("issue1", log);
+		ValueSetModel valuesmmodel = new DiscreteValueSetModel(log);
+		DefaultMapModel<StringModel, ValueSetModel> issuesmodel = new DefaultMapModel<StringModel, ValueSetModel>(
+				Collections.singletonMap(namemodel, valuesmmodel), log) {
+
+			@Override
+			public String getColumnName(int n) {
+				return n == 0 ? "issue" : "value";
+			}
+
+			@Override
+			public ValueSetModel create(StringModel key) {
+				// CALLER SHOULD ADD THIS TO ISSUE n++
+				return new DiscreteValueSetModel(log);
+			}
+
+			@Override
+			public int getMinimumSize() {
+				return 1;
+			}
+
+		};
+		DomainModel model = new DomainModel(new StringModel("testdomain", log),
+				issuesmodel, log);
+		model.addListener(new Listener<Event>() {
+
+			@Override
+			public void notifyChange(Event data) {
+				System.out.println("String changed : " + data);
+			}
+		});
+		f.getContentPane().add(new DomainEditorPanel(model, log),
+				BorderLayout.CENTER);
+		f.pack();
+		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		f.setVisible(true);
+		Thread.sleep(10000);
+		f.setVisible(false);
+	}
+}
Index: /domaineditor/src/test/java/geniusweb/domaineditor/ProfileEditorPanelTest.java
===================================================================
--- /domaineditor/src/test/java/geniusweb/domaineditor/ProfileEditorPanelTest.java	(revision 49)
+++ /domaineditor/src/test/java/geniusweb/domaineditor/ProfileEditorPanelTest.java	(revision 49)
@@ -0,0 +1,33 @@
+package geniusweb.domaineditor;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import org.junit.Test;
+
+import geniusweb.domaineditor.model.DomainModel;
+import geniusweb.domaineditor.model.profile.LinearAdditiveUtilitySpaceModel;
+import geniusweb.domaineditor.panels.profile.ProfileEditorPanel;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.panels.PopupReporter;
+
+public class ProfileEditorPanelTest {
+	@Test
+	public void test() throws InterruptedException {
+		JFrame frame = new JFrame();
+		JPanel panel = new JPanel(new BorderLayout());
+		Reporter log = new PopupReporter(frame);
+
+		DomainModel domain = new DomainModel(log);
+		LinearAdditiveUtilitySpaceModel lamodel = new LinearAdditiveUtilitySpaceModel(
+				domain, log);
+
+		frame.getContentPane().add(new ProfileEditorPanel(lamodel, log));
+		frame.pack();
+		frame.setVisible(true);
+		Thread.sleep(10000);
+		frame.setVisible(false);
+	}
+}
Index: /domaineditor/src/test/java/geniusweb/model/NumberValueSetModelTest.java
===================================================================
--- /domaineditor/src/test/java/geniusweb/model/NumberValueSetModelTest.java	(revision 49)
+++ /domaineditor/src/test/java/geniusweb/model/NumberValueSetModelTest.java	(revision 49)
@@ -0,0 +1,132 @@
+package geniusweb.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.math.BigDecimal;
+
+import org.junit.Test;
+
+import geniusweb.domaineditor.model.NumberValueSetModel;
+import geniusweb.issuevalue.NumberValueSet;
+import geniusweb.issuevalue.ValueSet;
+import tudelft.utilities.immutablelist.Range;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.NumberModel;
+
+public class NumberValueSetModelTest {
+	private final Reporter log = mock(Reporter.class);
+
+	@Test
+	public void smoke() {
+		new NumberValueSetModel(log);
+	}
+
+	@Test
+	public void testSomeGoodValues() {
+		NumberValueSetModel model = new NumberValueSetModel(log);
+		assertEquals(11, model.getList().getSize()); // default is 0...10
+		model.getLow().setValue(new BigDecimal("2"));
+		assertEquals(9, model.getList().getSize()); // 2..10
+		model.getHigh().setValue(new BigDecimal("3"));
+		assertEquals(2, model.getList().getSize()); // 2..3
+		model.getStep().setValue(new BigDecimal("0.1"));
+		assertEquals(11, model.getList().getSize()); // 2.0, 2.1, ...,3.0
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testIllegal1() {
+		new NumberValueSetModel(new NumberModel(BigDecimal.TEN, log),
+				new NumberModel(BigDecimal.ONE, log),
+				new NumberModel(BigDecimal.ONE, log), log);
+	}
+
+	@Test
+	public void testIllegal12() {
+		NumberValueSetModel n = new NumberValueSetModel(log);
+		// change low above high must log problem
+		n.getLow().setValue(BigDecimal.valueOf(20));
+		verify(log, times(1)).log(any(), any());
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testIllegal3() {
+		NumberValueSetModel model = new NumberValueSetModel(
+				new NumberModel(BigDecimal.TEN, log),
+				new NumberModel(BigDecimal.ONE, log),
+				new NumberModel(BigDecimal.ONE, log), log);
+		model.getLow().setValue(BigDecimal.valueOf(20));
+	}
+
+	@Test
+	public void testLowIncrease() {
+		NumberValueSetModel set = new NumberValueSetModel(
+				new NumberModel(BigDecimal.ZERO, log),
+				new NumberModel(BigDecimal.TEN, log),
+				new NumberModel(BigDecimal.ONE, log), log);
+		ValueSet v = new NumberValueSet(
+				new Range(BigDecimal.ONE, BigDecimal.TEN, BigDecimal.ONE));
+		set.setCurrentValue(v);
+
+	}
+
+	@Test
+	public void testHighDecrease() {
+		NumberValueSetModel set = new NumberValueSetModel(
+				new NumberModel(BigDecimal.ZERO, log),
+				new NumberModel(BigDecimal.TEN, log),
+				new NumberModel(BigDecimal.ONE, log), log);
+		ValueSet v = new NumberValueSet(
+				new Range(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.ONE));
+		set.setCurrentValue(v);
+
+	}
+
+	@Test
+	public void testIncreaseBoth() {
+		NumberValueSetModel set = new NumberValueSetModel(
+				new NumberModel(BigDecimal.ZERO, log),
+				new NumberModel(BigDecimal.ONE, log),
+				new NumberModel(BigDecimal.ONE, log), log);
+		ValueSet v = new NumberValueSet(
+				new Range(BigDecimal.ONE, BigDecimal.TEN, BigDecimal.ONE));
+		set.setCurrentValue(v);
+	}
+
+	@Test
+	public void testIncreaseBothMuch() {
+		NumberValueSetModel set = new NumberValueSetModel(
+				new NumberModel(BigDecimal.ZERO, log),
+				new NumberModel(BigDecimal.ONE, log),
+				new NumberModel(BigDecimal.ONE, log), log);
+		ValueSet v = new NumberValueSet(new Range(new BigDecimal("20"),
+				new BigDecimal("80"), BigDecimal.ONE));
+		set.setCurrentValue(v);
+	}
+
+	@Test
+	public void testDecreaseBoth() {
+		NumberValueSetModel set = new NumberValueSetModel(
+				new NumberModel(BigDecimal.ONE, log),
+				new NumberModel(BigDecimal.TEN, log),
+				new NumberModel(BigDecimal.ONE, log), log);
+		ValueSet v = new NumberValueSet(
+				new Range(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.ONE));
+		set.setCurrentValue(v);
+	}
+
+	@Test
+	public void testDecreaseBothMuch() {
+		NumberValueSetModel set = new NumberValueSetModel(
+				new NumberModel(new BigDecimal("20"), log),
+				new NumberModel(new BigDecimal("80"), log),
+				new NumberModel(BigDecimal.ONE, log), log);
+		ValueSet v = new NumberValueSet(
+				new Range(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.ONE));
+		set.setCurrentValue(v);
+	}
+
+}
Index: /domaineditor/src/test/java/geniusweb/panels/ComboBoxTest.java
===================================================================
--- /domaineditor/src/test/java/geniusweb/panels/ComboBoxTest.java	(revision 49)
+++ /domaineditor/src/test/java/geniusweb/panels/ComboBoxTest.java	(revision 49)
@@ -0,0 +1,117 @@
+package geniusweb.panels;
+
+import static org.mockito.Mockito.mock;
+
+import java.awt.BorderLayout;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JSeparator;
+
+import org.junit.Test;
+
+import geniusweb.domaineditor.model.DiscreteValueSetModel;
+import geniusweb.domaineditor.model.DomainModel;
+import geniusweb.domaineditor.model.ValueSetModel;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.mvc.model.DefaultListModel;
+import tudelft.utilities.mvc.model.DefaultMapModel;
+import tudelft.utilities.mvc.model.DefaultSelectionModel;
+import tudelft.utilities.mvc.model.MapModel;
+import tudelft.utilities.mvc.model.SelectionModel;
+import tudelft.utilities.mvc.model.StringModel;
+import tudelft.utilities.mvc.panels.ComboBox;
+
+public class ComboBoxTest {
+	private Reporter log = mock(Reporter.class);
+
+	@Test
+	public void GuiTest() throws InterruptedException {
+
+		StringModel a = new StringModel("apples", log);
+		StringModel b = new StringModel("bears", log);
+		StringModel c = new StringModel("carrots", log);
+
+		JFrame f = new JFrame();
+		JPanel panel = new JPanel(new BorderLayout());
+		f.getContentPane().add(panel);
+		DefaultListModel<StringModel> model = new DefaultListModel(
+				Arrays.asList(a, b, c), log) {
+
+		};
+		DefaultSelectionModel<StringModel> selectionmodel1 = new DefaultSelectionModel(
+				model);
+		panel.add(new ComboBox<StringModel>(selectionmodel1),
+				BorderLayout.NORTH);
+		panel.add(new JSeparator(), BorderLayout.CENTER);
+		panel.add(new ComboBox<StringModel>(selectionmodel1),
+				BorderLayout.SOUTH);
+		f.pack();
+		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		f.setVisible(true);
+		Thread.sleep(10000);
+		f.setVisible(false);
+	}
+
+	@Test
+	public void testEqualsDeep() {
+
+		StringModel redvalue = new StringModel("red", log);
+		StringModel greenvalue = new StringModel("green", log);
+		DiscreteValueSetModel issue1values = new DiscreteValueSetModel(
+				Arrays.asList(redvalue, greenvalue), log);
+
+		StringModel issue1 = new StringModel("issue", log);
+
+		SelectionModel issue1valuessel = new DefaultSelectionModel(
+				issue1values);
+		Map<StringModel, SelectionModel> a = Collections.singletonMap(issue1,
+				issue1valuessel);
+		DefaultMapModel<StringModel, SelectionModel> issuevalues = new DefaultMapModel<StringModel, SelectionModel>(
+				a, log) {
+
+			@Override
+			public String getColumnName(int n) {
+				return n == 0 ? "issue" : "value";
+			}
+
+			@Override
+			public SelectionModel create(StringModel key) {
+				throw new UnsupportedOperationException();
+			}
+
+			@Override
+			public int getMinimumSize() {
+				return 1;
+			}
+
+		};
+
+		MapModel<StringModel, ValueSetModel> issuevaluesmodel = new DefaultMapModel<StringModel, ValueSetModel>(
+				Collections.singletonMap(issue1, issue1values), log) {
+
+			@Override
+			public String getColumnName(int n) {
+				return n == 0 ? "issue" : "value";
+			}
+
+			@Override
+			public int getMinimumSize() {
+				return 1;
+			}
+
+			@Override
+			public ValueSetModel create(StringModel key) {
+				throw new UnsupportedOperationException();
+			}
+
+		};
+		DomainModel domain = new DomainModel(new StringModel("testdomain", log),
+				issuevaluesmodel, log);
+
+		// TODO test equals functions in ComboBoxModel
+	}
+}
Index: /events/pom.xml
===================================================================
--- /events/pom.xml	(revision 48)
+++ /events/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>events</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /exampleparties/anac2019/agentgg/pom.xml
===================================================================
--- /exampleparties/anac2019/agentgg/pom.xml	(revision 48)
+++ /exampleparties/anac2019/agentgg/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties.anac2019</groupId>
 	<artifactId>agentgg</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
@@ -60,5 +60,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
Index: /exampleparties/anac2019/winkyagent/pom.xml
===================================================================
--- /exampleparties/anac2019/winkyagent/pom.xml	(revision 48)
+++ /exampleparties/anac2019/winkyagent/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties.anac2019</groupId>
 	<artifactId>winkyagent</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
@@ -60,5 +60,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
Index: /exampleparties/boulware/pom.xml
===================================================================
--- /exampleparties/boulware/pom.xml	(revision 48)
+++ /exampleparties/boulware/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>boulware</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
Index: /exampleparties/comparebids/pom.xml
===================================================================
--- /exampleparties/comparebids/pom.xml	(revision 48)
+++ /exampleparties/comparebids/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>comparebids</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -53,5 +53,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
Index: /exampleparties/conceder/pom.xml
===================================================================
--- /exampleparties/conceder/pom.xml	(revision 48)
+++ /exampleparties/conceder/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>conceder</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
Index: /exampleparties/hardliner/pom.xml
===================================================================
--- /exampleparties/hardliner/pom.xml	(revision 48)
+++ /exampleparties/hardliner/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>hardliner</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
Index: /exampleparties/humangui/pom.xml
===================================================================
--- /exampleparties/humangui/pom.xml	(revision 48)
+++ /exampleparties/humangui/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>humangui</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /exampleparties/linear/pom.xml
===================================================================
--- /exampleparties/linear/pom.xml	(revision 48)
+++ /exampleparties/linear/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>linear</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
Index: /exampleparties/randomparty/pom.xml
===================================================================
--- /exampleparties/randomparty/pom.xml	(revision 48)
+++ /exampleparties/randomparty/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>randomparty</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
@@ -55,5 +55,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
Index: /exampleparties/randompartypy/pom.xml
===================================================================
--- /exampleparties/randompartypy/pom.xml	(revision 48)
+++ /exampleparties/randompartypy/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>randompyparty</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
Index: /exampleparties/simpleboa/pom.xml
===================================================================
--- /exampleparties/simpleboa/pom.xml	(revision 48)
+++ /exampleparties/simpleboa/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>simpleboaparty</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
Index: /exampleparties/simpleshaop/pom.xml
===================================================================
--- /exampleparties/simpleshaop/pom.xml	(revision 48)
+++ /exampleparties/simpleshaop/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>simpleshaop</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -53,5 +53,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
Index: /exampleparties/timedependentparty/pom.xml
===================================================================
--- /exampleparties/timedependentparty/pom.xml	(revision 48)
+++ /exampleparties/timedependentparty/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>timedependentparty</artifactId>
-	<version>2.1.3</version>  <!-- equals the geniusweb version -->
+	<version>2.1.4</version>  <!-- equals the geniusweb version -->
 	<packaging>jar</packaging>
 
@@ -53,5 +53,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
Index: /ip/pom.xml
===================================================================
--- /ip/pom.xml	(revision 48)
+++ /ip/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>ip</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /issuevalue/pom.xml
===================================================================
--- /issuevalue/pom.xml	(revision 48)
+++ /issuevalue/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>issuevalue</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -93,5 +93,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
Index: /issuevalue/src/main/java/geniusweb/issuevalue/Domain.java
===================================================================
--- /issuevalue/src/main/java/geniusweb/issuevalue/Domain.java	(revision 48)
+++ /issuevalue/src/main/java/geniusweb/issuevalue/Domain.java	(revision 49)
@@ -23,27 +23,27 @@
 	/**
 	 * 
-	 * @param shortName a short name for display/toString. This name must
-	 *                  contain simple characters only (a-z, A-Z, 0-9).
-	 * @param issues    the issues, Map with key: the issue name and value:
-	 *                  {@link ValueSet} with the allowed values for the issue.
+	 * @param name   a short name for display/toString. This name must contain
+	 *               simple characters only (a-z, A-Z, 0-9).
+	 * @param issues the issues, Map with key: the issue name and value:
+	 *               {@link ValueSet} with the allowed values for the issue.
 	 */
 	@JsonCreator
-	public Domain(@JsonProperty("name") String shortName,
+	public Domain(@JsonProperty("name") String name,
 			@JsonProperty("issuesValues") Map<String, ValueSet> issues) {
 		if (issues == null) {
 			throw new NullPointerException("issues=null");
 		}
-		if (shortName == null) {
-			throw new NullPointerException("shortName=null");
+		if (name == null) {
+			throw new NullPointerException("name=null");
 		}
-		if (!shortName.matches("[a-zA-Z0-9]+")) {
+		if (!name.matches("[a-zA-Z0-9]+")) {
 			throw new IllegalArgumentException(
 					"domain name can have only simple characters but found "
-							+ shortName);
+							+ name);
 		}
 		if (issues.isEmpty()) {
 			throw new IllegalArgumentException("issues is empty set");
 		}
-		this.name = shortName;
+		this.name = name;
 		this.issuesValues = new HashMap<>(issues);
 	}
Index: /issuevalue/src/main/java/geniusweb/issuevalue/NumberValueSet.java
===================================================================
--- /issuevalue/src/main/java/geniusweb/issuevalue/NumberValueSet.java	(revision 48)
+++ /issuevalue/src/main/java/geniusweb/issuevalue/NumberValueSet.java	(revision 49)
@@ -58,4 +58,7 @@
 	@Override
 	public NumberValue get(BigInteger index) {
+		if (index.compareTo(size()) > 0) {
+			return null;
+		}
 		return new NumberValue(range.get(index));
 	}
Index: /issuevalue/src/main/java/geniusweb/issuevalue/Value.java
===================================================================
--- /issuevalue/src/main/java/geniusweb/issuevalue/Value.java	(revision 48)
+++ /issuevalue/src/main/java/geniusweb/issuevalue/Value.java	(revision 49)
@@ -19,4 +19,8 @@
 @JsonDeserialize(using = ValueDeserializer.class)
 public interface Value {
+	/**
+	 * @return the contained value (String, BigDecimal)
+	 */
+	public Object getValue();
 
 }
Index: /logconverter/pom.xml
===================================================================
--- /logconverter/pom.xml	(revision 48)
+++ /logconverter/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>logconverter</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /opponentmodel/pom.xml
===================================================================
--- /opponentmodel/pom.xml	(revision 48)
+++ /opponentmodel/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>opponentmodel</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /party/pom.xml
===================================================================
--- /party/pom.xml	(revision 48)
+++ /party/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>party</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -52,5 +52,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 		<dependency>
Index: /pom.xml
===================================================================
--- /pom.xml	(revision 48)
+++ /pom.xml	(revision 49)
@@ -34,4 +34,5 @@
 		<module>ip</module>
 		<module>logconverter</module>
+		<module>domaineditor</module>
 	</modules>
 </project>
Index: /profile/pom.xml
===================================================================
--- /profile/pom.xml	(revision 48)
+++ /profile/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>profile</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -42,5 +42,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 
Index: /profile/src/main/java/geniusweb/profile/utilityspace/ProductOfValue.java
===================================================================
--- /profile/src/main/java/geniusweb/profile/utilityspace/ProductOfValue.java	(revision 48)
+++ /profile/src/main/java/geniusweb/profile/utilityspace/ProductOfValue.java	(revision 49)
@@ -73,3 +73,8 @@
 	}
 
+	@Override
+	public Object getValue() {
+		return getValues();
+	}
+
 }
Index: /profileconnection/pom.xml
===================================================================
--- /profileconnection/pom.xml	(revision 48)
+++ /profileconnection/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>profileconnection</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /protocol/pom.xml
===================================================================
--- /protocol/pom.xml	(revision 48)
+++ /protocol/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>protocol</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -56,5 +56,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 		<dependency>
Index: /pythonadapter/pom.xml
===================================================================
--- /pythonadapter/pom.xml	(revision 48)
+++ /pythonadapter/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>pythonadapter</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /references/pom.xml
===================================================================
--- /references/pom.xml	(revision 48)
+++ /references/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>references</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -32,5 +32,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 		<!-- the core, which includes Streaming API, shared low-level abstractions 
Index: /simplerunner/pom.xml
===================================================================
--- /simplerunner/pom.xml	(revision 48)
+++ /simplerunner/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>simplerunner</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /timeline/pom.xml
===================================================================
--- /timeline/pom.xml	(revision 48)
+++ /timeline/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>timeline</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
Index: /voting/pom.xml
===================================================================
--- /voting/pom.xml	(revision 48)
+++ /voting/pom.xml	(revision 49)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>voting</artifactId>
-	<version>2.1.3</version>
+	<version>2.1.4</version>
 	<packaging>jar</packaging>
 
@@ -42,5 +42,5 @@
 			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
-			<version>1.1.1</version>
+			<version>1.2.1</version>
 		</dependency>
 		<!-- the core, which includes Streaming API, shared low-level abstractions 
