+ public void moveFieldUp(Field field) {
+ checkNotNull(field, "field must not be null");
+ checkArgument(hasField(field), "field must belong to this profile");
+ checkArgument(getFieldIndex(field) > 0, "field index must be > 0");
+ int fieldIndex = getFieldIndex(field);
+ fields.remove(field);
+ fields.add(fieldIndex - 1, field);
+ }
+
+ /**
+ * Moves the given field down one position in the field list. The index of
+ * the field to move must be less than the index of the last field (because
+ * you obviously can not move the last field further down).
+ *
+ * @param field
+ * The field to move down
+ */
+ public void moveFieldDown(Field field) {
+ checkNotNull(field, "field must not be null");
+ checkArgument(hasField(field), "field must belong to this profile");
+ checkArgument(getFieldIndex(field) < fields.size() - 1, "field index must be < " + (fields.size() - 1));
+ int fieldIndex = getFieldIndex(field);
+ fields.remove(field);
+ fields.add(fieldIndex + 1, field);
+ }
+
+ /**
+ * Removes the given field.
+ *
+ * @param field
+ * The field to remove
+ */
+ public void removeField(Field field) {
+ checkNotNull(field, "field must not be null");
+ checkArgument(hasField(field), "field must belong to this profile");
+ fields.remove(field);
+ }
+
+ public Modifier modify() {
+ return new Modifier() {
+ private Optional<String> firstName = name.getFirst();
+ private Optional<String> middleName = name.getMiddle();
+ private Optional<String> lastName = name.getLast();
+ private Optional<Integer> birthYear = birthDate.getYear();
+ private Optional<Integer> birthMonth = birthDate.getMonth();
+ private Optional<Integer> birthDay = birthDate.getDay();
+
+ @Override
+ public Modifier setFirstName(String firstName) {
+ this.firstName = fromNullable(firstName);
+ return this;
+ }
+
+ @Override
+ public Modifier setMiddleName(String middleName) {
+ this.middleName = fromNullable(middleName);
+ return this;
+ }
+
+ @Override
+ public Modifier setLastName(String lastName) {
+ this.lastName = fromNullable(lastName);
+ return this;
+ }
+
+ @Override
+ public Modifier setBirthYear(Integer birthYear) {
+ this.birthYear = fromNullable(birthYear);
+ return this;
+ }
+
+ @Override
+ public Modifier setBirthMonth(Integer birthMonth) {
+ this.birthMonth = fromNullable(birthMonth);
+ return this;
+ }
+
+ @Override
+ public Modifier setBirthDay(Integer birthDay) {
+ this.birthDay = fromNullable(birthDay);
+ return this;
+ }
+
+ @Override
+ public Profile update() {
+ Profile.this.name = new Name(firstName, middleName, lastName);
+ Profile.this.birthDate = new BirthDate(birthYear, birthMonth, birthDay);
+ return Profile.this;
+ }
+ };
+ }
+
+ public interface Modifier {
+
+ Modifier setFirstName(String firstName);
+ Modifier setMiddleName(String middleName);
+ Modifier setLastName(String lastName);
+ Modifier setBirthYear(Integer birthYear);
+ Modifier setBirthMonth(Integer birthMonth);
+ Modifier setBirthDay(Integer birthDay);
+ Profile update();
+
+ }
+
+ //
+ // PRIVATE METHODS
+ //
+
+ /**
+ * Returns the index of the field with the given name.
+ *
+ * @param field
+ * The name of the field
+ * @return The index of the field, or {@code -1} if there is no field with
+ * the given name
+ */
+ private int getFieldIndex(Field field) {
+ return fields.indexOf(field);