001package org.xbib.standardnumber; 002 003import org.xbib.standardnumber.check.iso7064.MOD112; 004 005import java.util.regex.Matcher; 006import java.util.regex.Pattern; 007 008/** 009 * ISO 27729 International Standard Name Identifier (ISNI) 010 * 011 * The International Standard Name Identifier (ISNI) is a method for uniquely identifying 012 * the public identities of contributors to media content such as books, TV programmes, 013 * and newspaper articles. Such an identifier consists of 16 numerical digits divided 014 * into four blocks. 015 * 016 * Checksum is in accordance to ISO/IEC 7064:2003, MOD 11-2 017 */ 018public class ISNI extends AbstractStandardNumber implements Comparable<ISNI>, StandardNumber { 019 020 private final static Pattern PATTERN = Pattern.compile("[\\p{Digit}xX\\-\\s]{16,24}"); 021 022 private String value; 023 024 private String formatted; 025 026 private boolean createWithChecksum; 027 028 @Override 029 public String type() { 030 return "isni"; 031 } 032 033 /** 034 * Creates a new ISNI 035 * 036 * @param value the value 037 */ 038 @Override 039 public ISNI set(CharSequence value) { 040 this.value = value != null ? value.toString() : null; 041 return this; 042 } 043 044 @Override 045 public ISNI createChecksum(boolean createWithChecksum) { 046 this.createWithChecksum = createWithChecksum; 047 return this; 048 } 049 050 @Override 051 public int compareTo(ISNI isni) { 052 return value != null ? value.compareTo((isni).normalizedValue()) : -1; 053 } 054 055 @Override 056 public boolean isValid() { 057 return value != null && !value.isEmpty() && check(); 058 } 059 060 @Override 061 public ISNI verify() throws NumberFormatException { 062 if (!check()) { 063 throw new NumberFormatException("bad createChecksum"); 064 } 065 return this; 066 } 067 068 /** 069 * Returns the value representation of the standard number 070 * @return value 071 */ 072 @Override 073 public String normalizedValue() { 074 return value; 075 } 076 077 /** 078 * Format this number 079 * 080 * @return the formatted number 081 */ 082 @Override 083 public String format() { 084 if (formatted == null) { 085 this.formatted = value; 086 } 087 return formatted; 088 } 089 090 @Override 091 public ISNI normalize() { 092 Matcher m = PATTERN.matcher(value); 093 if (m.find()) { 094 this.value = clean(value.substring(m.start(), m.end())); 095 } 096 return this; 097 } 098 099 @Override 100 public ISNI reset() { 101 this.value = null; 102 this.formatted = null; 103 this.createWithChecksum = false; 104 return this; 105 } 106 107 private final static MOD112 check = new MOD112(); 108 109 private boolean check() { 110 if (createWithChecksum) { 111 this.value = check.encode(value.length() < 16 ? value : value.substring(0, value.length()-1)); 112 } 113 if (value.length() < 16) { 114 return false; 115 } 116 return check.verify(value); 117 } 118 119 private String clean(String isbn) { 120 StringBuilder sb = new StringBuilder(isbn); 121 int i = sb.indexOf("-"); 122 while (i >= 0) { 123 sb.deleteCharAt(i); 124 i = sb.indexOf("-"); 125 } 126 i = sb.indexOf(" "); 127 while (i >= 0) { 128 sb.deleteCharAt(i); 129 i = sb.indexOf(" "); 130 } 131 return sb.toString(); 132 } 133 134}