+
+ @Override
+ public NameSchemaType getSchemeName() {
+ return NameSchemaType.WESTERN;
+ }
+
+ @Override
+ public String toAbbreviatedString() {
+ return firstNames[0].getValue() + " " + lastNames[0].getValue().charAt(0) + ".";
+ }
+ }
+
+ private int id;
+
+ private int ownerId;
+
+ /**
+ * Only resolved lazily to resolve circular referencing with {@link User} on
+ * {@link User#getPreferredName()}. Resolved based on {@link #ownerId}.
+ */
+ private User owner;
+
+ private NamePart[] parts;
+
+ private SchemedName scheme;
+
+ /**
+ * This name should not get verifed anymore and therefore not be displayed
+ * to the RA-Agent. This state is irrevocable.
+ */
+ private boolean deprecated;
+
+ private Name(GigiResultSet rs) {
+ ownerId = rs.getInt(1);
+ id = rs.getInt(2);
+ deprecated = rs.getString("deprecated") != null;
+ try (GigiPreparedStatement partFetcher = new GigiPreparedStatement("SELECT `type`, `value` FROM `nameParts` WHERE `id`=? ORDER BY `position` ASC", true)) {
+ partFetcher.setInt(1, id);
+ GigiResultSet rs1 = partFetcher.executeQuery();
+ rs1.last();
+ NamePart[] dt = new NamePart[rs1.getRow()];
+ rs1.beforeFirst();
+ for (int i = 0; rs1.next(); i++) {
+ dt[i] = new NamePart(rs1);
+ }
+ parts = dt;
+ scheme = detectScheme();
+ }
+
+ }
+
+ public Name(User u, NamePart... np) throws GigiApiException {
+ synchronized (Name.class) {
+ parts = np;
+ owner = u;
+ scheme = detectScheme();
+ if (scheme == null) {
+ throw new GigiApiException("Name particles don't match up for any known name scheme.");
+ }
+ try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO `names` SET `uid`=?, `type`=?::`nameSchemaType`")) {
+ inserter.setInt(1, u.getId());
+ inserter.setEnum(2, scheme.getSchemeName());
+ inserter.execute();
+ id = inserter.lastInsertId();
+ }
+ try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO `nameParts` SET `id`=?, `position`=?, `type`=?::`namePartType`, `value`=?")) {
+ inserter.setInt(1, id);
+ for (int i = 0; i < np.length; i++) {
+ inserter.setInt(2, i);
+ inserter.setEnum(3, np[i].getType());
+ inserter.setString(4, np[i].getValue());
+ inserter.execute();
+ }
+ }
+ cache.put(this);
+ }
+ }
+
+ private SchemedName detectScheme() {
+ if (parts.length == 1 && parts[0].getType() == NamePartType.SINGLE_NAME) {
+ return new SingleName(parts[0]);
+ }
+ int suffixCount = 0;
+ int lastCount = 0;
+ int firstCount = 0;
+ int stage = 0;
+ for (NamePart p : parts) {
+ if (p.getType() == NamePartType.LAST_NAME) {
+ lastCount++;
+ if (stage < 1) {
+ stage = 1;
+ } else if (stage != 1) {
+ return null;
+ }
+ } else if (p.getType() == NamePartType.FIRST_NAME) {
+ firstCount++;
+ if (stage != 0) {
+ return null;
+ }
+ } else if (p.getType() == NamePartType.SUFFIX) {
+ suffixCount++;
+ if (stage < 2) {
+ stage = 2;
+ } else if (stage != 2) {
+ return null;
+ }
+
+ } else {
+ return null;
+ }
+ }
+ if (firstCount == 0 || lastCount == 0) {
+ return null;
+ }
+ NamePart[] firstNames = new NamePart[firstCount];
+ NamePart[] lastNames = new NamePart[lastCount];
+ NamePart[] suffixes = new NamePart[suffixCount];
+ int fn = 0;
+ int ln = 0;
+ int sn = 0;
+ for (NamePart p : parts) {
+ if (p.getType() == NamePartType.FIRST_NAME) {
+ firstNames[fn++] = p;
+ } else if (p.getType() == NamePartType.SUFFIX) {
+ suffixes[sn++] = p;
+ } else if (p.getType() == NamePartType.LAST_NAME) {
+ lastNames[ln++] = p;