+public class Profile implements Fingerprintable {
+
+ /** The Sone this profile belongs to. */
+ private final Sone sone;
+
+ private volatile Name name = new Name();
+ private volatile BirthDate birthDate = new BirthDate();
+
+ /** The ID of the avatar image. */
+ private volatile String avatar;
+
+ /** Additional fields in the profile. */
+ private final List<Field> fields = Collections.synchronizedList(new ArrayList<Field>());
+
+ /**
+ * Creates a new empty profile.
+ *
+ * @param sone
+ * The Sone this profile belongs to
+ */
+ public Profile(Sone sone) {
+ this.sone = sone;
+ }
+
+ /**
+ * Creates a copy of a profile.
+ *
+ * @param profile
+ * The profile to copy
+ */
+ public Profile(Profile profile) {
+ this.sone = profile.sone;
+ this.name = profile.name;
+ this.birthDate = profile.birthDate;
+ this.avatar = profile.avatar;
+ this.fields.addAll(profile.fields);
+ }
+
+ //
+ // ACCESSORS
+ //
+
+ /**
+ * Returns the Sone this profile belongs to.
+ *
+ * @return The Sone this profile belongs to
+ */
+ public Sone getSone() {
+ return sone;
+ }
+
+ public String getFirstName() {
+ return name.getFirst().orNull();
+ }
+
+ public String getMiddleName() {
+ return name.getMiddle().orNull();
+ }
+
+ public String getLastName() {
+ return name.getLast().orNull();
+ }
+
+ public Integer getBirthDay() {
+ return birthDate.getDay().orNull();
+ }
+
+ public Integer getBirthMonth() {
+ return birthDate.getMonth().orNull();
+ }
+
+ public Integer getBirthYear() {
+ return birthDate.getYear().orNull();
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public Profile setAvatar(Optional<String> avatarId) {
+ this.avatar = avatarId.orNull();
+ return this;
+ }
+
+ public List<Field> getFields() {
+ return new ArrayList<Field>(fields);
+ }
+
+ public boolean hasField(Field field) {
+ return fields.contains(field);
+ }
+
+ public Optional<Field> getFieldById(String fieldId) {
+ checkNotNull(fieldId, "fieldId must not be null");
+ for (Field field : fields) {
+ if (field.getId().equals(fieldId)) {
+ return of(field);
+ }
+ }
+ return absent();
+ }
+
+ public Optional<Field> getFieldByName(String fieldName) {
+ for (Field field : fields) {
+ if (field.getName().equals(fieldName)) {
+ return of(field);
+ }
+ }
+ return absent();
+ }
+
+ public Field addField(String fieldName) throws IllegalArgumentException {
+ checkNotNull(fieldName, "fieldName must not be null");
+ checkArgument(fieldName.length() > 0, "fieldName must not be empty");
+ checkArgument(!getFieldByName(fieldName).isPresent(), "fieldName must be unique");
+ @SuppressWarnings("synthetic-access")
+ Field field = new Field(fieldName);
+ fields.add(field);
+ return field;
+ }
+
+ 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));
+ }