gt: 		final Builder builder = new Builder();
context: package org.kareha.hareka.server.game.user;
  
  import java.util.Date;
  
  import javax.xml.bind.annotation.XmlAccessType;
  import javax.xml.bind.annotation.XmlAccessorType;
  import javax.xml.bind.annotation.XmlElement;
  import javax.xml.bind.annotation.XmlType;
  import javax.xml.bind.annotation.adapters.XmlAdapter;
  import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
  
  import org.kareha.hareka.annotation.Immutable;
  import org.kareha.hareka.annotation.PackagePrivate;
  import org.kareha.hareka.annotation.Private;
  import org.kareha.hareka.key.KeyId;
  
  @Immutable
  @XmlJavaTypeAdapter(UserNote.Adapter.class)
  public class UserNote {
  
  	public static class Builder {
  
  		private UserNote template;
  		@Private
  		KeyId userId;
  		@Private
  		Long version;
  		@Private
  		KeyId creatorId;
  		@Private
  		Long creationDate;
  		@Private
  		KeyId editorId;
  		@Private
  		Long lastEditedDate;
  		@Private
  		String nickname;
  		@Private
  		String note;
  
  		public Builder template(final UserNote v) {
  			template = v;
  			return this;
  		}
  
  		public Builder userId(final KeyId v) {
  			userId = v;
  			return this;
  		}
  
  		public Builder version(final long v) {
  			version = v;
  			return this;
  		}
  
  		public Builder creatorId(final KeyId v) {
  			creatorId = v;
  			return this;
  		}
  
  		public Builder creationDate(final long v) {
  			creationDate = v;
  			return this;
  		}
  
  		public Builder editorId(final KeyId v) {
  			editorId = v;
  			return this;
  		}
  
  		public Builder lastEditedDate(final long v) {
  			lastEditedDate = v;
  			return this;
  		}
  
  		public Builder nickname(final String v) {
  			nickname = v;
  			return this;
  		}
  
  		public Builder note(final String v) {
  			note = v;
  			return this;
  		}
  
  		public UserNote build() {
  			if (template != null) {
  				if (userId == null) {
  					userId = template.userId;
  				}
  				if (version == null) {
  					version = template.version;
  				}
  				if (creatorId == null) {
  					creatorId = template.creatorId;
  				}
  				if (creationDate == null) {
  					creationDate = template.creationDate;
  				}
  				if (editorId == null) {
  					editorId = template.editorId;
  				}
  				if (lastEditedDate == null) {
  					lastEditedDate = template.lastEditedDate;
  				}
  				if (nickname == null) {
  					nickname = template.nickname;
  				}
  				if (note == null) {
  					note = template.note;
  				}
  			}
  			return new UserNote(this);
  		}
  
  	}
  
  	@Private
  	final KeyId userId;
  	@Private
  	final long version;
  	@Private
  	final KeyId creatorId;
  	@Private
  	final long creationDate;
  	@Private
  	final KeyId editorId;
  	@Private
  	final long lastEditedDate;
  	@Private
  	final String nickname;
  	@Private
  	final String note;
  
  	@Private
  	UserNote(final Builder builder) {
  		if (builder == null) {
  			throw new IllegalArgumentException("null");
  		}
  		if (builder.userId == null) {
  			throw new IllegalArgumentException("userId is null");
  		}
  		userId = builder.userId;
  		version = builder.version;
  		creatorId = builder.creatorId;
  		creationDate = builder.creationDate;
  		editorId = builder.editorId;
  		lastEditedDate = builder.lastEditedDate;
  		nickname = builder.nickname;
  		note = builder.note;
  	}
  
  	// XXX not used yet
  	@PackagePrivate
  	UserNote(final KeyId userId, final KeyId creatorId, final String nickname, final String note) {
  		if (userId == null) {
  			throw new IllegalArgumentException("null");
  		}
  		this.userId = userId;
  		version = 0;
  		this.creatorId = creatorId;
  		creationDate = System.currentTimeMillis();
  		editorId = creatorId;
  		lastEditedDate = creationDate;
  		this.nickname = nickname;
  		this.note = note;
  	}
  
  	@Override
  	public boolean equals(final Object obj) {
  		if (!(obj instanceof UserNote)) {
  			return false;
  		}
  		final UserNote userNote = (UserNote) obj;
  		return userNote.userId.equals(userId);
  	}
  
  	@Override
  	public int hashCode() {
  		return userId.hashCode();
  	}
  
  	@XmlType(name = "userNote")
  	@XmlAccessorType(XmlAccessType.NONE)
  	private static class Adapted {
  
  		@XmlElement(name = "user")
  		private KeyId userId;
  		@XmlElement
  		private long version;
  		@XmlElement(name = "creator")
  		private KeyId creatorId;
  		@XmlElement
  		private Date creationDate;
  		@XmlElement(name = "editor")
  		private KeyId editorId;
  		@XmlElement
  		private Date lastEditedDate;
  		@XmlElement
  		private String nickname;
  		@XmlElement
  		private String note;
  
  		@SuppressWarnings("unused")
  		private Adapted() {
  			// used by JAXB
  		}
  
  		@Private
  		Adapted(final UserNote v) {
  			userId = v.userId;
  			version = v.version;
  			creatorId = v.creatorId;
  			creationDate = new Date(v.creationDate);
  			editorId = v.editorId;
  			lastEditedDate = new Date(v.lastEditedDate);
  			nickname = v.nickname;
  			note = v.note;
  		}
  
  		@Private
  		UserNote unmarshal() {
  			final Builder builder = new Builder();
  			builder.userId(userId).version(version);
  			builder.creatorId(creatorId).creationDate(creationDate.getTime());
  			builder.editorId(editorId).lastEditedDate(lastEditedDate.getTime());
  			builder.nickname(nickname).note(note);
  			return builder.build();
  		}
  
  	}
  
  	@Private
  	Adapted marshal() {
  		return new Adapted(this);
  	}
  
  	static class Adapter extends XmlAdapter<Adapted, UserNote> {
  
  		@Override
  		public Adapted marshal(final UserNote v) throws Exception {
  			if (v == null) {
  				return null;
  			}
  			return v.marshal();
  		}
  
  		@Override
  		public UserNote unmarshal(final Adapted v) throws Exception {
  			if (v == null) {
  				return null;
  			}
  			return v.unmarshal();
  		}
  
  	}
  
  	public KeyId getUserId() {
  		return userId;
  	}
  
  	public String getNickname() {
  		return nickname;
  	}
  
  	// XXX not used yet
  	@PackagePrivate
  	UserNote changeNickname(final KeyId editorId, final String nickname) {
  		final Builder builder = new Builder();
  		builder.template(this);
  		builder.version(version + 1);
  		builder.editorId(editorId).lastEditedDate(System.currentTimeMillis());
  		builder.nickname(nickname);
  		return builder.build();
  	}
  
  	public String getNote() {
  		return note;
  	}
  
  	// XXX not used yet
  	@PackagePrivate
  	UserNote changeNote(final KeyId editorId, final String note) {
  