Add function that converts a Sone into its insert URI.
[Sone.git] / src / main / java / net / pterodactylus / sone / data / Profile.java
index db55227..61cf291 100644 (file)
 
 package net.pterodactylus.sone.data;
 
+import static com.google.common.base.Optional.absent;
 import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Optional.of;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+import static java.util.UUID.randomUUID;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.UUID;
 
 import com.google.common.base.Optional;
 import com.google.common.hash.Hasher;
@@ -88,205 +91,110 @@ public class Profile implements Fingerprintable {
                return sone;
        }
 
-       /**
-        * Returns the first name.
-        *
-        * @return The first name
-        */
        public String getFirstName() {
                return name.getFirst().orNull();
        }
 
-       /**
-        * Returns the middle name(s).
-        *
-        * @return The middle name
-        */
        public String getMiddleName() {
                return name.getMiddle().orNull();
        }
 
-       /**
-        * Returns the last name.
-        *
-        * @return The last name
-        */
        public String getLastName() {
                return name.getLast().orNull();
        }
 
-       /**
-        * Returns the day of the birth date.
-        *
-        * @return The day of the birth date (from 1 to 31)
-        */
        public Integer getBirthDay() {
                return birthDate.getDay().orNull();
        }
 
-       /**
-        * Returns the month of the birth date.
-        *
-        * @return The month of the birth date (from 1 to 12)
-        */
        public Integer getBirthMonth() {
                return birthDate.getMonth().orNull();
        }
 
-       /**
-        * Returns the year of the birth date.
-        *
-        * @return The year of the birth date
-        */
        public Integer getBirthYear() {
                return birthDate.getYear().orNull();
        }
 
-       /**
-        * Returns the ID of the currently selected avatar image.
-        *
-        * @return The ID of the currently selected avatar image, or {@code null} if
-        *         no avatar is selected.
-        */
        public String getAvatar() {
                return avatar;
        }
 
-       /**
-        * Sets the avatar image.
-        *
-        * @param avatar
-        *            The new avatar image, or {@code null} to not select an avatar
-        *            image.
-        * @return This Sone
-        */
-       public Profile setAvatar(Image avatar) {
-               if (avatar == null) {
-                       this.avatar = null;
-                       return this;
-               }
-               checkArgument(avatar.getSone().equals(sone), "avatar must belong to Sone");
-               this.avatar = avatar.getId();
+       public Profile setAvatar(Optional<String> avatarId) {
+               this.avatar = avatarId.orNull();
                return this;
        }
 
-       /**
-        * Returns the fields of this profile.
-        *
-        * @return The fields of this profile
-        */
        public List<Field> getFields() {
                return new ArrayList<Field>(fields);
        }
 
-       /**
-        * Returns whether this profile contains the given field.
-        *
-        * @param field
-        *            The field to check for
-        * @return {@code true} if this profile contains the field, false otherwise
-        */
        public boolean hasField(Field field) {
                return fields.contains(field);
        }
 
-       /**
-        * Returns the field with the given ID.
-        *
-        * @param fieldId
-        *            The ID of the field to get
-        * @return The field, or {@code null} if this profile does not contain a
-        *         field with the given ID
-        */
-       public Field getFieldById(String fieldId) {
+       public Optional<Field> getFieldById(String fieldId) {
                checkNotNull(fieldId, "fieldId must not be null");
                for (Field field : fields) {
                        if (field.getId().equals(fieldId)) {
-                               return field;
+                               return of(field);
                        }
                }
-               return null;
+               return absent();
        }
 
-       /**
-        * Returns the field with the given name.
-        *
-        * @param fieldName
-        *            The name of the field to get
-        * @return The field, or {@code null} if this profile does not contain a
-        *         field with the given name
-        */
-       public Field getFieldByName(String fieldName) {
+       public Optional<Field> getFieldByName(String fieldName) {
                for (Field field : fields) {
                        if (field.getName().equals(fieldName)) {
-                               return field;
+                               return of(field);
                        }
                }
-               return null;
+               return absent();
        }
 
-       /**
-        * Appends a new field to the list of fields.
-        *
-        * @param fieldName
-        *            The name of the new field
-        * @return The new field
-        * @throws IllegalArgumentException
-        *             if the name is not valid
-        */
        public Field addField(String fieldName) throws IllegalArgumentException {
                checkNotNull(fieldName, "fieldName must not be null");
                checkArgument(fieldName.length() > 0, "fieldName must not be empty");
-               checkState(getFieldByName(fieldName) == null, "fieldName must be unique");
+               checkArgument(!getFieldByName(fieldName).isPresent(), "fieldName must be unique");
                @SuppressWarnings("synthetic-access")
-               Field field = new Field().setName(fieldName);
+               Field field = new Field(fieldName);
                fields.add(field);
                return field;
        }
 
-       /**
-        * Moves the given field up one position in the field list. The index of the
-        * field to move must be greater than {@code 0} (because you obviously can
-        * not move the first field further up).
-        *
-        * @param field
-        *            The field to move up
-        */
+       public void renameField(Field field, String newName) {
+               int indexOfField = getFieldIndex(field);
+               if (indexOfField == -1) {
+                       return;
+               }
+               fields.set(indexOfField, new Field(field.getId(), newName, field.getValue()));
+       }
+
+       public void setField(Field field, String newValue) {
+               int indexOfField = getFieldIndex(field);
+               if (indexOfField == -1) {
+                       return;
+               }
+               fields.set(indexOfField, new Field(field.getId(), field.getName(), newValue));
+       }
+
        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);
+               fields.add(max(fieldIndex - 1, 0), 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);
+               fields.add(min(fieldIndex + 1, fields.size()), 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);
        }
 
@@ -376,9 +284,6 @@ public class Profile implements Fingerprintable {
        // INTERFACE Fingerprintable
        //
 
-       /**
-        * {@inheritDoc}
-        */
        @Override
        public String getFingerprint() {
                Hasher hash = Hashing.sha256().newHasher();
@@ -390,7 +295,9 @@ public class Profile implements Fingerprintable {
                }
                hash.putString("ContactInformation(");
                for (Field field : fields) {
-                       hash.putString(field.getName()).putString("(").putString(field.getValue()).putString(")");
+                       if (field.getValue() != null) {
+                               hash.putString(field.getName()).putString("(").putString(field.getValue()).putString(")");
+                       }
                }
                hash.putString(")");
                hash.putString(")");
@@ -403,98 +310,38 @@ public class Profile implements Fingerprintable {
         *
         * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
         */
-       public class Field {
+       public static class Field {
 
-               /** The ID of the field. */
                private final String id;
+               private final String name;
+               private final String value;
 
-               /** The name of the field. */
-               private String name;
-
-               /** The value of the field. */
-               private String value;
+               public Field(String name) {
+                       this(name, null);
+               }
 
-               /**
-                * Creates a new field with a random ID.
-                */
-               private Field() {
-                       this(UUID.randomUUID().toString());
+               public Field(String name, String value) {
+                       this(randomUUID().toString(), name, value);
                }
 
-               /**
-                * Creates a new field with the given ID.
-                *
-                * @param id
-                *            The ID of the field
-                */
-               private Field(String id) {
+               public Field(String id, String name, String value) {
                        this.id = checkNotNull(id, "id must not be null");
+                       this.name = name;
+                       this.value = value;
                }
 
-               /**
-                * Returns the ID of this field.
-                *
-                * @return The ID of this field
-                */
                public String getId() {
                        return id;
                }
 
-               /**
-                * Returns the name of this field.
-                *
-                * @return The name of this field
-                */
                public String getName() {
                        return name;
                }
 
-               /**
-                * Sets the name of this field. The name must not be {@code null} and
-                * must not match any other fields in this profile but my match the name
-                * of this field.
-                *
-                * @param name
-                *            The new name of this field
-                * @return This field
-                */
-               public Field setName(String name) {
-                       checkNotNull(name, "name must not be null");
-                       checkArgument(getFieldByName(name) == null, "name must be unique");
-                       this.name = name;
-                       return this;
-               }
-
-               /**
-                * Returns the value of this field.
-                *
-                * @return The value of this field
-                */
                public String getValue() {
                        return value;
                }
 
-               /**
-                * Sets the value of this field. While {@code null} is allowed, no
-                * guarantees are made that {@code null} values are correctly persisted
-                * across restarts of the plugin!
-                *
-                * @param value
-                *            The new value of this field
-                * @return This field
-                */
-               public Field setValue(String value) {
-                       this.value = value;
-                       return this;
-               }
-
-               //
-               // OBJECT METHODS
-               //
-
-               /**
-                * {@inheritDoc}
-                */
                @Override
                public boolean equals(Object object) {
                        if (!(object instanceof Field)) {
@@ -504,9 +351,6 @@ public class Profile implements Fingerprintable {
                        return id.equals(field.id);
                }
 
-               /**
-                * {@inheritDoc}
-                */
                @Override
                public int hashCode() {
                        return id.hashCode();