X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=src%2Forg%2Fcacert%2Fgigi%2FdbObjects%2FName.java;fp=src%2Forg%2Fcacert%2Fgigi%2FdbObjects%2FName.java;h=0000000000000000000000000000000000000000;hp=df9e1ff6f19660005f115cd63b23624bba06697b;hb=bccd4cc0dba0f89aa045b113bac46eb8cc1dab4e;hpb=c9ed09f0007fc2c813815be927a5a24b23dab83c diff --git a/src/org/cacert/gigi/dbObjects/Name.java b/src/org/cacert/gigi/dbObjects/Name.java deleted file mode 100644 index df9e1ff6..00000000 --- a/src/org/cacert/gigi/dbObjects/Name.java +++ /dev/null @@ -1,460 +0,0 @@ -package org.cacert.gigi.dbObjects; - -import java.io.PrintWriter; -import java.util.Map; - -import org.cacert.gigi.GigiApiException; -import org.cacert.gigi.database.DBEnum; -import org.cacert.gigi.database.GigiPreparedStatement; -import org.cacert.gigi.database.GigiResultSet; -import org.cacert.gigi.dbObjects.NamePart.NamePartType; -import org.cacert.gigi.localisation.Language; -import org.cacert.gigi.output.template.Outputable; -import org.cacert.gigi.util.HTMLEncoder; - -public class Name implements Outputable, IdCachable { - - public static enum NameSchemaType implements DBEnum { - SINGLE, WESTERN; - - @Override - public String getDBName() { - return toString().toLowerCase(); - } - - } - - private abstract static class SchemedName { - - /** - * @see Name#matches(String) - */ - public abstract boolean matches(String text); - - public abstract String toPreferredString(); - - /** - * @see Name#toAbbreviatedString() - */ - public abstract String toAbbreviatedString(); - - public abstract NameSchemaType getSchemeName(); - - /** - * @see Name#output(PrintWriter, Language, Map) - */ - public abstract void output(PrintWriter out); - - } - - private static class SingleName extends SchemedName { - - private NamePart singlePart; - - public SingleName(NamePart singlePart) { - this.singlePart = singlePart; - } - - @Override - public boolean matches(String text) { - return text.equals(singlePart.getValue()); - } - - @Override - public String toPreferredString() { - return singlePart.getValue(); - } - - @Override - public String toAbbreviatedString() { - return singlePart.getValue(); - } - - @Override - public NameSchemaType getSchemeName() { - return NameSchemaType.SINGLE; - } - - @Override - public void output(PrintWriter out) { - out.print(""); - out.print(HTMLEncoder.encodeHTML(singlePart.getValue())); - out.println(""); - } - } - - /** - * Naming scheme where any first name and the first last name is required. - * Requires first names in arbitrary order. Last names and suffixes in - * correct order. - */ - private static class WesternName extends SchemedName { - - private NamePart[] firstNames; - - private NamePart[] lastNames; - - private NamePart[] suffixes; - - public WesternName(NamePart[] firstName, NamePart lastName[], NamePart[] suffixes) { - if (lastName.length < 1 || firstName.length < 1) { - throw new Error("Requires at least one first and one last name"); - } - this.lastNames = lastName; - this.firstNames = firstName; - this.suffixes = suffixes; - } - - @Override - public boolean matches(String text) { - String[] tokens = text.split(" "); - - NamePart mandatoryLN = lastNames[0]; - for (int i = 0; i < tokens.length; i++) { - if (tokens[i].equals(mandatoryLN.getValue())) { - if (tryMatchFirst(tokens, i) && tryMatchLastSuff(tokens, i)) { - return true; - } - - } - } - return false; - } - - private boolean tryMatchLastSuff(String[] tokens, int lastName) { - int userInputPos = lastName + 1; - boolean currentlyMatchingLastNames = true; - int referencePos = 1; - while ((currentlyMatchingLastNames || referencePos < suffixes.length) && (userInputPos < tokens.length)) { - // we break when we match suffixes and there is no - // reference-suffix left - if (currentlyMatchingLastNames) { - if (referencePos >= lastNames.length) { - referencePos = 0; - currentlyMatchingLastNames = false; - } else if (tokens[userInputPos].equals(lastNames[referencePos].getValue())) { - userInputPos++; - referencePos++; - } else { - referencePos++; - } - } else { - if (tokens[userInputPos].equals(suffixes[referencePos].getValue())) { - userInputPos++; - referencePos++; - } else { - referencePos++; - } - } - } - if (userInputPos >= tokens.length) { - // all name parts are covered we're done here - return true; - } - return false; - } - - private boolean tryMatchFirst(String[] tokens, int lastName) { - if (lastName == 0) { - return false; - } - boolean[] fnUsed = new boolean[firstNames.length]; - for (int i = 0; i < lastName; i++) { - boolean found = false; - for (int j = 0; j < fnUsed.length; j++) { - if ( !fnUsed[j] && firstNames[j].getValue().equals(tokens[i])) { - fnUsed[j] = true; - found = true; - break; - } - } - if ( !found) { - return false; - } - } - return true; - } - - @Override - public String toPreferredString() { - StringBuilder res = new StringBuilder(); - appendArray(res, firstNames); - appendArray(res, lastNames); - appendArray(res, suffixes); - res.deleteCharAt(res.length() - 1); - return res.toString(); - } - - @Override - public void output(PrintWriter out) { - outputNameParts(out, "fname", firstNames); - outputNameParts(out, "lname", lastNames); - outputNameParts(out, "suffix", suffixes); - } - - private void outputNameParts(PrintWriter out, String type, NamePart[] input) { - StringBuilder res; - res = new StringBuilder(); - appendArray(res, input); - if (res.length() > 0) { - res.deleteCharAt(res.length() - 1); - out.print(""); - out.print(HTMLEncoder.encodeHTML(res.toString())); - out.println(""); - } - } - - private void appendArray(StringBuilder res, NamePart[] ps) { - for (int i = 0; i < ps.length; i++) { - res.append(ps[i].getValue()); - res.append(" "); - } - } - - @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; - } - } - - return new WesternName(firstNames, lastNames, suffixes); - } - - /** - * Outputs an HTML variant suitable for locations where special UI features - * should indicate the different Name Parts. - */ - @Override - public void output(PrintWriter out, Language l, Map vars) { - out.print(""); - scheme.output(out); - out.print(" "); - } - - /** - * Tests, if this name fits into the given string. - * - * @param text - * the name to test against - * @return true, iff this name matches. - */ - public boolean matches(String text) { - if ( !text.equals(text.trim())) { - return false; - } - return scheme.matches(text); - } - - @Override - public String toString() { - return scheme.toPreferredString(); - } - - /** - * Transforms this String into a short form. This short form should not be - * unique. (For "western" names this would be - * "firstName firstCharOfLastName.".) - * - * @return the short form of the name - */ - public String toAbbreviatedString() { - return scheme.toAbbreviatedString(); - } - - public int getAssurancePoints() { - try (GigiPreparedStatement query = new GigiPreparedStatement("SELECT SUM(`points`) FROM (SELECT DISTINCT ON (`from`, `method`) `points` FROM `notary` WHERE `to`=? AND `deleted` IS NULL AND (`expire` IS NULL OR `expire` > CURRENT_TIMESTAMP) ORDER BY `from`, `method`, `when` DESC) AS p")) { - query.setInt(1, getId()); - - GigiResultSet rs = query.executeQuery(); - int points = 0; - - if (rs.next()) { - points = rs.getInt(1); - } - - return points; - } - } - - @Override - public int getId() { - return id; - } - - private static ObjectCache cache = new ObjectCache<>(); - - public synchronized static Name getById(int id) { - Name cacheRes = cache.get(id); - if (cacheRes != null) { - return cacheRes; - } - - try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `uid`, `id`, `deprecated` FROM `names` WHERE `deleted` IS NULL AND `id` = ?")) { - ps.setInt(1, id); - GigiResultSet rs = ps.executeQuery(); - if ( !rs.next()) { - return null; - } - - Name c = new Name(rs); - cache.put(c); - return c; - } - } - - public NamePart[] getParts() { - return parts; - } - - public void remove() { - synchronized (Name.class) { - cache.remove(this); - try (GigiPreparedStatement ps = new GigiPreparedStatement("UPDATE `names` SET `deleted` = now() WHERE `id`=?")) { - ps.setInt(1, id); - ps.executeUpdate(); - } - } - } - - public synchronized void deprecate() { - deprecated = true; - try (GigiPreparedStatement ps = new GigiPreparedStatement("UPDATE `names` SET `deprecated`=now() WHERE `id`=?")) { - ps.setInt(1, id); - ps.executeUpdate(); - } - } - - public boolean isDeprecated() { - return deprecated; - } - - public synchronized User getOwner() { - if (owner == null) { - owner = User.getById(ownerId); - } - return owner; - } -}