Index: events/src/main/java/geniusweb/actions/Action.java
===================================================================
--- events/src/main/java/geniusweb/actions/Action.java	(revision 30)
+++ events/src/main/java/geniusweb/actions/Action.java	(revision 31)
@@ -20,5 +20,6 @@
 		@JsonSubTypes.Type(value = Votes.class),
 		@JsonSubTypes.Type(value = VoteWithValue.class),
-		@JsonSubTypes.Type(value = VotesWithValue.class) })
+		@JsonSubTypes.Type(value = VotesWithValue.class),
+		@JsonSubTypes.Type(value = LearningDone.class) })
 public interface Action {
 	/**
Index: events/src/main/java/geniusweb/actions/FileLocation.java
===================================================================
--- events/src/main/java/geniusweb/actions/FileLocation.java	(revision 31)
+++ events/src/main/java/geniusweb/actions/FileLocation.java	(revision 31)
@@ -0,0 +1,101 @@
+package geniusweb.actions;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.UUID;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * This contains a "system independent" {@link File}. This is represented by a
+ * {@link UUID}. The file may or may not yet exist (depending on whether your
+ * party already wrote some contents in that file in previous runs), may or may
+ * not be empty (your choice), and can contain any type of data. The original
+ * intent of this is that parties can store learned data in this file, while the
+ * name can be kept for later re-use in later runs (eg negotiation sessions) on
+ * the same machine.
+ * <p>
+ * This file is to be used locally on some other machine (typically a
+ * partiesserver). This object itself only contains a file name.
+ * {@link #getFile()} turns it into a system-specific {@link File}. <br>
+ * <h2>WARNING</h2> if used multiple times on different machines, multiple,
+ * separate files will be involved, there is no magical synchronization of
+ * multiple items with the same UUID used on different machines.
+ */
+public class FileLocation {
+
+	@JsonValue
+	private final UUID name;
+
+	private final static String TMP = System.getProperty("java.io.tmpdir");
+	private final static String GENIUSWEB = "geniusweb";
+	private final static Path rootpath = Paths.get(TMP, GENIUSWEB);
+	private final static File rootfolder = rootpath.toFile();
+
+	/**
+	 * @param name the name of the file (must be UUID to prevent injection of
+	 *             bad filenames like /.. or C:) Use {@link #FileLocation()} to
+	 *             create new FileLocation. That should ensure a new UUID that
+	 *             does not collide with existing ones.
+	 */
+	@JsonCreator
+	public FileLocation(UUID name) {
+		this.name = name;
+	}
+
+	/**
+	 * Default constructor creates a new "random" FileLocation.
+	 */
+	public FileLocation() {
+		if (!rootfolder.exists()) {
+			rootfolder.mkdir();
+			System.out
+					.println("created FileLocation root dir at " + rootfolder);
+		}
+		this.name = UUID.randomUUID();
+	}
+
+	/**
+	 * 
+	 * @return the UUID string
+	 */
+	public String getUUIDString() {
+		return name.toString();
+	}
+
+	public File getFile() {
+		return Paths.get(TMP, GENIUSWEB, name.toString()).toFile();
+	}
+
+	@Override
+	public String toString() {
+		return "FileLocation[" + name + "]";
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((name == null) ? 0 : name.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		FileLocation other = (FileLocation) obj;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		return true;
+	}
+}
Index: events/src/main/java/geniusweb/actions/LearningDone.java
===================================================================
--- events/src/main/java/geniusweb/actions/LearningDone.java	(revision 31)
+++ events/src/main/java/geniusweb/actions/LearningDone.java	(revision 31)
@@ -0,0 +1,20 @@
+package geniusweb.actions;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Indicates that a party turns away from the negotiation and.
+ *
+ */
+public class LearningDone extends AbstractAction {
+	@JsonCreator
+	public LearningDone(@JsonProperty("actor") PartyId id) {
+		super(id);
+	}
+
+	@Override
+	public String toString() {
+		return "LearningDone[" + getActor() + "]";
+	}
+}
Index: events/src/main/java/geniusweb/actions/PartyId.java
===================================================================
--- events/src/main/java/geniusweb/actions/PartyId.java	(revision 30)
+++ events/src/main/java/geniusweb/actions/PartyId.java	(revision 31)
@@ -4,9 +4,12 @@
 
 /**
- * Globally (that is, worldwide) unique ID of a party in a negotiation.
- * Normally, negotiation parties should not create new Party IDs as all needed
- * IDs should be provided by the protocol. Serializes only as part of a bigger
- * object. This ID may contain parts of an ip address but that address should
- * not be used to make contact.
+ * Unique ID of a party in a negotiation. The name should start with a short
+ * string indicating the party (eg, the party name plus some machine
+ * identifier), optionally followed by an "_", and more characters to make the
+ * partyid unique. We require the name and "-" so that the string up to the
+ * first "-" can be used to determine between sessions which opponents are
+ * instances of the same class.
+ * <h2>Note</h2> Normally, negotiation parties should not create new Party IDs
+ * as all needed IDs should be provided by the protocol.
  */
 public final class PartyId {
