+ private int getFieldIndex(Field field) {
+ return fields.indexOf(field);
+ }
+
+ //
+ // INTERFACE Fingerprintable
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getFingerprint() {
+ Hasher hash = Hashing.sha256().newHasher();
+ hash.putString("Profile(");
+ hash.putString(name.getFingerprint());
+ hash.putString(birthDate.getFingerprint());
+ if (avatar != null) {
+ hash.putString("Avatar(").putString(avatar).putString(")");
+ }
+ hash.putString("ContactInformation(");
+ for (Field field : fields) {
+ hash.putString(field.getName()).putString("(").putString(field.getValue()).putString(")");
+ }
+ hash.putString(")");
+ hash.putString(")");
+
+ return hash.hash().toString();
+ }
+
+ /**
+ * Container for a profile field.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+ public static class Field {
+
+ private final String id;
+ private final String name;
+ private final String value;
+
+ public Field(String name) {
+ this(name, null);
+ }
+
+ public Field(String name, String value) {
+ this(randomUUID().toString(), name, value);
+ }
+
+ public Field(String id, String name, String value) {
+ this.id = checkNotNull(id, "id must not be null");
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof Field)) {
+ return false;
+ }
+ Field field = (Field) object;
+ return id.equals(field.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ }
+
+ public static class Name implements Fingerprintable {
+
+ private final Optional<String> first;
+ private final Optional<String> middle;
+ private final Optional<String> last;
+
+ public Name() {
+ this(Optional.<String>absent(), Optional.<String>absent(), Optional.<String>absent());
+ }
+
+ public Name(Optional<String> first, Optional<String> middle, Optional<String> last) {
+ this.first = first;
+ this.middle = middle;
+ this.last = last;
+ }
+
+ public Optional<String> getFirst() {
+ return first;
+ }
+
+ public Optional<String> getMiddle() {
+ return middle;
+ }
+
+ public Optional<String> getLast() {
+ return last;
+ }
+
+ @Override
+ public String getFingerprint() {
+ Hasher hash = Hashing.sha256().newHasher();
+ hash.putString("Name(");
+ if (first.isPresent()) {
+ hash.putString("First(").putString(first.get()).putString(")");
+ }
+ if (middle.isPresent()) {
+ hash.putString("Middle(").putString(middle.get()).putString(")");
+ }
+ if (last.isPresent()) {
+ hash.putString("Last(").putString(last.get()).putString(")");
+ }
+ hash.putString(")");
+ return hash.hash().toString();
+ }
+
+ }
+
+ public static class BirthDate implements Fingerprintable {
+
+ private final Optional<Integer> year;
+ private final Optional<Integer> month;
+ private final Optional<Integer> day;
+
+ public BirthDate() {
+ this(Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.<Integer>absent());
+ }
+
+ public BirthDate(Optional<Integer> year, Optional<Integer> month, Optional<Integer> day) {
+ this.year = year;
+ this.month = month;
+ this.day = day;
+ }
+
+ public Optional<Integer> getYear() {
+ return year;
+ }
+
+ public Optional<Integer> getMonth() {
+ return month;
+ }
+
+ public Optional<Integer> getDay() {
+ return day;
+ }
+
+ @Override
+ public String getFingerprint() {
+ Hasher hash = Hashing.sha256().newHasher();
+ hash.putString("Birthdate(");
+ if (year.isPresent()) {
+ hash.putString("Year(").putInt(year.get()).putString(")");
+ }
+ if (month.isPresent()) {
+ hash.putString("Month(").putInt(month.get()).putString(")");
+ }
+ if (day.isPresent()) {
+ hash.putString("Day(").putInt(day.get()).putString(")");
+ }
+ hash.putString(")");
+ return hash.hash().toString();
+ }
+